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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/docs/ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,6 @@ The full Selenide UI suite takes ~1.5h per DB, so it does **not** run on every P
- To force a specific UI IT to run on every PR, add `@Tag("smoke")` to that class (keep the list small - smoke must stay fast).
- Shard-routing tags: `@Tag("sample")` sits on the `SampleProjectsIT` base (inherited by every sample-project IT); `@Tag("camel")` sits on each IT in `ui/tests/camel` (their `PredefinedProjectIT` base is shared with non-camel tests, so the base cannot carry it — tag new camel ITs individually). These route classes into the `samples` CI shard; everything else UI stays in the `ui` shard.
- `@Tag("slow")` is the **fourth shard**, and it is a *balancing* tag, not a semantic one: it holds the long poles of both families (currently the api classes above ~55 s and the browser journeys above ~110 s), because without them `api` and `ui` are the critical path while `samples` idles. Membership is a judgement about measured CI time — re-check it when the shard times drift apart, and note that mistagging can only unbalance the shards, never drop an IT (`api` is the untagged complement). It does **not** affect the PR smoke gate: a `slow` api IT is still untagged-`ui`, so `!ui | smoke` still selects it. It cannot rebalance `api`, whose cost is uniform per class - see the budget note above.
- `@Tag("upgrade")` is outside the shards (#7641): `UpgradeFromPreviousReleaseIT` runs the release named in `tests/UPGRADE_FROM` as its published image on a Testcontainers PostgreSQL, lets it write a deployment (an intent project with rows, a running process, a fired job), then boots the build under test on that database and a copy of its repository folder. It needs Docker and pulls a ~1 GB image, so the `api` shards and the PR gate exclude it (`& !upgrade`) and the `upgrade-test` job is its only selector - nightly, and in `release.yml`, where `release-docker-images` needs it. The release job writes the version it released into `tests/UPGRADE_FROM` in its "for development" commit. A new tag that must stay out of the shards needs the same `& !upgrade`-style exclusion on the `api` expression of BOTH legs in `build.yml` and `nightly.yml`, or the untagged complement picks it up.

`codeql.yml`, `release.yml` cover CodeQL and Maven Central release respectively.
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ jobs:
matrix:
shard:
- name: api
groups: "!ui & !slow"
groups: "!ui & !slow & !upgrade"
- name: ui
groups: "ui & !slow & !sample & !camel"
- name: samples
Expand Down Expand Up @@ -293,7 +293,7 @@ jobs:
matrix:
shard:
- name: api
groups: "!ui & !slow"
groups: "!ui & !slow & !upgrade"
- name: ui
groups: "ui & !slow & !sample & !camel"
- name: samples
Expand Down
67 changes: 65 additions & 2 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
matrix:
shard:
- name: api
groups: "!ui & !slow"
groups: "!ui & !slow & !upgrade"
- name: ui
groups: "ui & !slow & !sample & !camel"
- name: samples
Expand Down Expand Up @@ -114,14 +114,77 @@ jobs:
name: ${{ env.ARTIFACT_NAME }}
path: tests/tests-integrations/build/reports/tests

# The release under test booted on a deployment the PREVIOUS release wrote (#7641) - every other
# IT boots on an empty database. UpgradeFromPreviousReleaseIT runs tests/UPGRADE_FROM as its
# published image on a PostgreSQL of its own (Testcontainers), so the job needs Docker but no
# database service, and it is the only selector of the `upgrade` tag the api shard excludes.
upgrade-test:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Cache local Maven repository
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven-

- name: Set up JDK Corretto 24
uses: actions/setup-java@v4
with:
distribution: 'corretto'
java-version: '24'
architecture: x64

- name: Install NodeJS
uses: actions/setup-node@v4
with:
node-version: 22.x

- name: Install TypeScript and esbuild
run: npm install -g typescript@5.9.3 esbuild

- name: Install ttyd (prebuilt)
run: |
sudo apt update
sudo apt install -y ttyd

- name: Upgrade from the previous release
run: |
echo "Upgrading from dirigiblelabs/dirigible:$(cat tests/UPGRADE_FROM)"
mvn clean install -P integration-tests -Dit.groups=upgrade

- name: Upload integration test reports
uses: actions/upload-artifact@v4
if: always()
with:
retention-days: 3
name: failsafe-reports-upgrade-${{ github.run_attempt }}
path: |
tests/tests-integrations/target/failsafe-reports
tests/tests-integrations/target/surefire-reports
if-no-files-found: ignore

- name: Assert the upgrade test ran
run: |
ran=$(ls tests/tests-integrations/target/failsafe-reports/TEST-*UpgradeFromPreviousReleaseIT.xml 2>/dev/null | wc -l)
if [ "$ran" -eq 0 ]; then
echo "::error::UpgradeFromPreviousReleaseIT did not run - the upgrade tag selected nothing (see #7215)"
exit 1
fi

integration-tests-postgresql:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shard:
- name: api
groups: "!ui & !slow"
groups: "!ui & !slow & !upgrade"
- name: ui
groups: "ui & !slow & !sample & !camel"
- name: samples
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ jobs:
# (including two full clone -> generate -> validate app lifecycles). The heavy Selenide
# suite (@Tag "ui") runs nightly and on master push - see nightly.yml and build.yml.
- name: Smoke integration tests (H2)
run: mvn clean install -P integration-tests -Dit.groups="!ui | smoke"
run: mvn clean install -P integration-tests -Dit.groups="(!ui | smoke) & !upgrade"

# Guards #7215: a tag expression that discovers nothing leaves the reports directory absent
# and the build green, so what ran is asserted by count instead of by the job's colour.
Expand Down
69 changes: 68 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,71 @@ permissions:
id-token: write

jobs:
# The release under test booted on a deployment the PREVIOUS release wrote (#7641) - every other
# IT boots on an empty database. UpgradeFromPreviousReleaseIT runs tests/UPGRADE_FROM as its
# published image on a PostgreSQL of its own (Testcontainers), so the job needs Docker but no
# database service, and it is the only selector of the `upgrade` tag the api shard excludes.
upgrade-test:
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Cache local Maven repository
uses: actions/cache@v4
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-maven-

- name: Set up JDK Corretto 24
uses: actions/setup-java@v4
with:
distribution: 'corretto'
java-version: '24'
architecture: x64

- name: Install NodeJS
uses: actions/setup-node@v4
with:
node-version: 22.x

- name: Install TypeScript and esbuild
run: npm install -g typescript@5.9.3 esbuild

- name: Install ttyd (prebuilt)
run: |
sudo apt update
sudo apt install -y ttyd

- name: Upgrade from the previous release
run: |
echo "Upgrading from dirigiblelabs/dirigible:$(cat tests/UPGRADE_FROM)"
mvn clean install -P integration-tests -Dit.groups=upgrade

- name: Upload integration test reports
uses: actions/upload-artifact@v4
if: always()
with:
retention-days: 3
name: failsafe-reports-upgrade-${{ github.run_attempt }}
path: |
tests/tests-integrations/target/failsafe-reports
tests/tests-integrations/target/surefire-reports
if-no-files-found: ignore

- name: Assert the upgrade test ran
run: |
ran=$(ls tests/tests-integrations/target/failsafe-reports/TEST-*UpgradeFromPreviousReleaseIT.xml 2>/dev/null | wc -l)
if [ "$ran" -eq 0 ]; then
echo "::error::UpgradeFromPreviousReleaseIT did not run - the upgrade tag selected nothing (see #7215)"
exit 1
fi

release-docker-images:
needs: upgrade-test
runs-on: ${{ matrix.runner }}
strategy:
matrix:
Expand Down Expand Up @@ -204,8 +268,11 @@ jobs:
run: mvn versions:set -DnewVersion=${{ github.event.inputs.snapshotVersion }}

- name: "Git: Commit Snapshot Version"
# tests/UPGRADE_FROM names the release the upgrade test starts from: from here on, the one
# this run has just released.
run: |
git add '**pom.xml'
echo "${{ github.event.inputs.releaseVersion }}" > tests/UPGRADE_FROM
git add '**pom.xml' tests/UPGRADE_FROM
git commit -m "version set to ${{ github.event.inputs.snapshotVersion }} for development"

#---------------Publish to Maven Central-----------------#
Expand Down
1 change: 1 addition & 0 deletions tests/UPGRADE_FROM
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
14.74.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (c) 2010-2026 Eclipse Dirigible contributors
*
* All rights reserved. This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v2.0 which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* SPDX-FileCopyrightText: Eclipse Dirigible contributors SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.dirigible.tests.framework.upgrade;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

/**
* The release an upgrade test starts from. It is kept in ONE place, {@code tests/UPGRADE_FROM},
* which the release workflow bumps to the version it has just released, so master is always tested
* against the release before it. The system property {@value #OVERRIDE_PROPERTY} overrides it - to
* try an upgrade from an older release, say.
*/
public final class PreviousRelease {

/** The system property that overrides the file. */
public static final String OVERRIDE_PROPERTY = "dirigible.upgrade.from";

/** The file that names the previous release. */
static final String FILE_NAME = "UPGRADE_FROM";

private PreviousRelease() {}

/**
* The tag of the previous release's {@code dirigiblelabs/dirigible} image.
*
* @return the tag, e.g. {@code 14.74.0}
*/
public static String tag() {
String override = System.getProperty(OVERRIDE_PROPERTY);
if (override != null && !override.isBlank()) {
return override.strip();
}
return read(locate(Path.of("")
.toAbsolutePath()));
}

/**
* Finds {@code tests/UPGRADE_FROM} from wherever the build runs: the tests module itself, or any
* folder below the repository root.
*/
static Path locate(Path start) {
for (Path folder = start; folder != null; folder = folder.getParent()) {
for (Path candidate : new Path[] {folder.resolve(FILE_NAME), folder.resolve("tests")
.resolve(FILE_NAME)}) {
if (Files.isRegularFile(candidate)) {
return candidate;
}
}
}
throw new IllegalStateException(
"No tests/" + FILE_NAME + " above [" + start + "] - it names the release an upgrade test starts from");
}

private static String read(Path file) {
try {
String tag = Files.readString(file, StandardCharsets.UTF_8)
.strip();
if (tag.isEmpty()) {
throw new IllegalStateException("[" + file + "] is empty - it must name the release an upgrade test starts from");
}
return tag;
} catch (IOException ex) {
throw new UncheckedIOException("Cannot read [" + file + "]", ex);
}
}
}
Loading
Loading