Compare commits

..
Author SHA1 Message Date
james.maes 49372e0b98 Add .circleci/config.yml 2026-10-15 11:18:39 -05:00
12 changed files with 67 additions and 162 deletions

No files matched your search

+28 -11
View File
@@ -1,14 +1,31 @@
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/reference/configuration-reference/
version: 2.1
setup: true
orbs:
qqq-orb: kingsrook/qqq-orb@0.8
# Define a job to be invoked later in a workflow.
# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#jobs-overview & https://circleci.com/docs/reference/configuration-reference/#jobs
jobs:
say-hello:
# Specify the execution environment. You can specify an image from Docker Hub or use one of our convenience images from CircleCI's Developer Hub.
# See: https://circleci.com/docs/guides/execution-managed/executor-intro/ & https://circleci.com/docs/reference/configuration-reference/#executor-job
docker:
# Specify the version you desire here
# See: https://circleci.com/developer/images/image/cimg/base
- image: cimg/base:current
# Add steps to the job
# See: https://circleci.com/docs/guides/orchestrate/jobs-steps/#steps-overview & https://circleci.com/docs/reference/configuration-reference/#steps
steps:
# Checkout the code as the first step.
- checkout
- run:
name: "Say hello"
command: "echo Hello, World!"
# Orchestrate jobs using workflows
# See: https://circleci.com/docs/guides/orchestrate/workflows/ & https://circleci.com/docs/reference/configuration-reference/#workflows
workflows:
setup:
say-hello-workflow: # This is the name of the workflow, feel free to change it to better match your workflow.
# Inside the workflow, you define the jobs you want to run.
jobs:
- qqq-orb/generate_pipeline:
orb_version: '0.8'
filters:
branches:
ignore: automation/qbit-rc-pending
tags:
only: /^v\d+\.\d+\.\d+$/
- say-hello
-7
View File
@@ -1,7 +0,0 @@
name: build
on:
push:
jobs:
maven:
uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/maven.yaml@v1
secrets: inherit
-23
View File
@@ -1,23 +0,0 @@
name: CodeQL
'on':
push:
branches:
- main
- develop
- release/**
- hotfix/**
pull_request: {}
schedule:
- cron: 41 16 * * 0
workflow_dispatch: {}
permissions:
contents: read
actions: read
security-events: write
packages: read
concurrency:
group: codeql-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
analyze:
uses: QRun-IO/qqq-orb/.github/workflows/qbit-codeql.yml@c288a8864fe9054f68410e1d78f5863aea4c4d22
+13 -62
View File
@@ -1,74 +1,25 @@
# Cut the next release candidate (QRun-IO/qqq docs/QRUN-QBIT-REPO-STANDARD.md, C6):
# run this workflow by hand, or merge a develop PR labelled `release:rc`. It merges develop into
# the release line and the release/* push runs CircleCI publish_release_candidate.
name: Release candidate
'on':
on:
workflow_dispatch:
inputs:
dry_run:
description: Plan a cut without changing release state
description: Print the plan without merging or creating branches
type: boolean
default: false
finalize:
description: Retry finalization of an existing cut; do not cut another RC
type: boolean
default: false
recover:
description: Recover the same published RC after a deployment timeout; never
reupload
type: boolean
default: false
circle_build:
description: Original Circle publisher build number (recovery only)
type: string
default: ''
merge_sha:
description: Existing cut merge_sha (finalize retry only)
type: string
default: ''
bump_sha:
description: Existing cut bump_sha (finalize retry only)
type: string
default: ''
branch:
description: Existing cut branch (finalize retry only)
type: string
default: ''
version:
description: Existing cut version (finalize retry only)
type: string
default: ''
pull_request:
types:
- closed
branches:
- develop
repository_dispatch:
types:
- qbit-rc-published
types: [closed]
branches: [develop]
permissions:
contents: write
actions: read
checks: read
jobs:
release-rc:
if: github.event_name == 'workflow_dispatch' || github.event_name == 'repository_dispatch'
|| (github.event_name == 'pull_request' && github.event.pull_request.merged
== true && github.event.pull_request.base.ref == 'develop' && contains(github.event.pull_request.labels.*.name,
'release:rc'))
uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@cc30f599e63c8e41629c99d23395bac1adb8bc44
if: github.event_name == 'workflow_dispatch' || (github.event.pull_request.merged == true && contains(github.event.pull_request.labels.*.name, 'release:rc'))
uses: QRun-IO/.github/.github/workflows/qbit-release-rc.yml@main
with:
dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false
}}
finalize: ${{ github.event_name == 'repository_dispatch' || (github.event_name
== 'workflow_dispatch' && inputs.finalize) }}
recover: ${{ github.event_name == 'workflow_dispatch' && inputs.recover || false
}}
circle_build: ${{ github.event_name == 'workflow_dispatch' && inputs.circle_build
|| '' }}
merge_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.merge_sha
|| inputs.merge_sha || '' }}
bump_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.bump_sha
|| inputs.bump_sha || '' }}
branch: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.branch
|| inputs.branch || '' }}
version: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.version
|| inputs.version || '' }}
secrets: inherit
dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run }}
-16
View File
@@ -1,16 +0,0 @@
profile: qbit
orb_version: '0.8'
default_branch: develop
java_version: '21'
browsers: true
api_checks: false
docs_only: false
release_on_main: false
release_tag_policy: stable
test_branch_policy: non-release
publish:
snapshot: true
release_candidate: true
release: true
asciidoc: false
release_completion: true
-11
View File
@@ -5,17 +5,6 @@ and [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Changed
- Reconciled legacy release-branch history with the current Gitea CI while retaining the develop
SNAPSHOT revision, so normal RC cuts can merge cleanly.
### Fixed
- SQL changelog headers: explanatory "-- Include it from the host..." comments were parsed as a
licensed Liquibase `include` directive. Replaced with neutral wording; changeset bodies and
schema are unchanged.
## [0.1.0] - Unreleased
### Added
+1 -1
View File
@@ -25,7 +25,7 @@ section E (summary in [docs/DESIGN.md](docs/DESIGN.md)).
<dependency>
<groupId>com.kingsrook.qbits</groupId>
<artifactId>qbit-cluster</artifactId>
<version>0.1.0-RC.1</version><!-- first release; see GitHub releases for the latest -->
<version>0.1.0-RC.1</version>
</dependency>
```
+15 -4
View File
@@ -18,8 +18,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<properties>
<qqq.version>4.1.0-RC.26</qqq.version> <!-- feeds qbit-build-parent's qqq-bom-pom import -->
<revision>0.3.0-SNAPSHOT</revision>
<revision>0.1.0-RC.1</revision>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<jacoco.version>0.8.15</jacoco.version>
@@ -29,7 +28,7 @@
<parent>
<groupId>com.kingsrook</groupId>
<artifactId>qbit-build-parent</artifactId>
<version>2.2.1</version>
<version>2.0.0</version>
</parent>
<groupId>com.kingsrook.qbits</groupId>
@@ -212,7 +211,7 @@
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<qqq.snapshot.version>4.1.0-RC.26</qqq.snapshot.version>
<qqq.snapshot.version>4.1.0-SNAPSHOT</qqq.snapshot.version>
</properties>
<dependencyManagement>
<dependencies>
@@ -225,6 +224,18 @@
</dependency>
</dependencies>
</dependencyManagement>
<repositories>
<repository>
<id>sonatype-snapshots</id>
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>
</project>
@@ -67,6 +67,8 @@ public class ClusterNodesWidgetRenderer extends AbstractWidgetRenderer
static final String NODE = "node";
static final String STATUS = "status";
static final String HEARTBEAT = "heartbeat";
static final String WHERE = "where";
static final String VERSION = "version";
@@ -94,7 +96,7 @@ public class ClusterNodesWidgetRenderer extends AbstractWidgetRenderer
}
TableData table = new TableData(null, List.of(
column("Role", ROLE), column("Node", NODE), column("Status", STATUS), column("Last heartbeat", HEARTBEAT)), rows)
column("Role", ROLE), column("Node", NODE), column("Status", STATUS), column("Last heartbeat", HEARTBEAT), column("Where", WHERE), column("Version", VERSION)), rows)
.withNoRowsFoundHTML("No nodes are running. A node appears here once it starts with the Cluster qbit.")
.withRowsPerPage(50)
.withHidePaginationDropdown(true);
@@ -110,29 +112,17 @@ public class ClusterNodesWidgetRenderer extends AbstractWidgetRenderer
{
Map<String, Object> row = new LinkedHashMap<>();
row.put(ROLE, roleLabel(role));
row.put(NODE, nodeText(node));
row.put(NODE, node.getValueString(ClusterTables.NODE_ID));
row.put(STATUS, statusText(node));
row.put(HEARTBEAT, age(node.getValueInstant(ClusterTables.HEARTBEAT_AT), now));
row.put(WHERE, Stream.of(node.getValueString(ClusterTables.K8S_NODE_NAME), node.getValueString(ClusterTables.ZONE), node.getValueString(ClusterTables.DEPLOYMENT))
.filter(StringUtils::hasContent).collect(Collectors.joining(", ")));
row.put(VERSION, node.getValueString(ClusterTables.VERSION) == null ? "" : node.getValueString(ClusterTables.VERSION));
return (row);
}
/*******************************************************************************
** The node id, with where it runs and its version folded in (four columns
** keep the table readable at every width): "web-7f9 (k8s-2, website-backend, 0.1.110)".
*******************************************************************************/
static String nodeText(QRecord node)
{
String details = Stream.of(node.getValueString(ClusterTables.K8S_NODE_NAME), node.getValueString(ClusterTables.ZONE), node.getValueString(ClusterTables.DEPLOYMENT),
node.getValueString(ClusterTables.VERSION))
.filter(StringUtils::hasContent).collect(Collectors.joining(", "));
String nodeId = node.getValueString(ClusterTables.NODE_ID);
return (details.isEmpty() ? nodeId : nodeId + " (" + details + ")");
}
/*******************************************************************************
** "Up", "Draining", "Up, drain requested", "Lost".
*******************************************************************************/
@@ -3,7 +3,7 @@
-- https://www.apache.org/licenses/LICENSE-2.0
-- qbit-cluster schema (QRun-IO/qqq docs/specs/2026-10-15-cluster-ha-design.md section E).
-- Load this file from the host's master changelog, then the defaults:
-- Include it from the host's master changelog, then the defaults:
--
-- - include: { file: db/liquibase/qbit-cluster/cluster.changelog.sql }
-- - include: { file: db/liquibase/qbit-cluster/cluster-defaults.changelog.sql }
@@ -89,14 +89,7 @@ class ClusterQBitProducerTest extends BaseClusterTest
assertThat(QAlertTypeMetaData.of(qInstance, ClusterAlerts.NODE_LOST)).isNotNull();
assertThat(HealthChecksMetaData.ofOrWithNew(qInstance).getChecks()).anyMatch(check -> ClusterHeartbeatHealthCheck.NAME.equals(check.getName()));
assertThat(qInstance.getRuntimeServices()).extracting(reference -> reference.getName()).containsOnlyOnce(ClusterRuntimeService.class.getName());
////////////////////////////////////////////////////////////////////
// the version comes from the build (filtered qbit-cluster.properties) //
////////////////////////////////////////////////////////////////////
assertThat(ClusterQBitProducer.version()).matches("[0-9]+[.][0-9]+[.][0-9]+(-[A-Za-z0-9.]+)?");
if(System.getProperty("qbit.artifactVersion") != null)
{
assertThat(ClusterQBitProducer.version()).isEqualTo(System.getProperty("qbit.artifactVersion"));
}
assertThat(ClusterQBitProducer.version()).isEqualTo("0.1.0-RC.1");
}
@@ -118,7 +118,7 @@ class ClusterSettingsWidgetHealthTest extends BaseClusterTest
assertThat(rows.get(0).get("heartbeat")).isEqualTo("5 hours ago");
assertThat(rows.get(2).get("status")).isEqualTo("Up, drain requested");
assertThat(rows.get(3).get("heartbeat")).isEqualTo("3 minutes ago");
assertThat(table.getColumns()).as("four columns: readable at every width").hasSize(4);
assertThat(table.getColumns()).hasSize(6);
assertThat(lost).isNotNull();
assertThat(ClusterNodesWidgetRenderer.class).isNotNull();