S19: establish engineering repository
This commit is contained in:
46
templates/common/.gitea/workflows/build.yaml
Normal file
46
templates/common/.gitea/workflows/build.yaml
Normal file
@@ -0,0 +1,46 @@
|
||||
name: Build, test and publish
|
||||
on:
|
||||
push:
|
||||
branches: ['**']
|
||||
|
||||
jobs:
|
||||
verify:
|
||||
runs-on: @RUNNER@
|
||||
env:
|
||||
CI: 'true'
|
||||
TARGET_PLATFORM: ${{ vars.TARGET_PLATFORM }}
|
||||
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
||||
CI_REPOSITORY: ${{ gitea.repository }}
|
||||
CI_COMMIT: ${{ gitea.sha }}
|
||||
CI_REF: ${{ gitea.ref }}
|
||||
CI_RUN_ID: ${{ gitea.run_id }}
|
||||
steps:
|
||||
- name: Check out pushed commit
|
||||
uses: https://github.com/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Verify pinned engineering resources
|
||||
run: python3 scripts/engineering.py --check
|
||||
- name: Identify workflow attempt
|
||||
# Gitea 1.25 does not populate gitea.run_attempt. Use a unique value for
|
||||
# container names and diagnostic artifacts, including reruns of one SHA.
|
||||
run: java generated/ci/Ci.java attempt
|
||||
- name: Build and test both images
|
||||
run: java generated/ci/Ci.java verify
|
||||
- name: Publish verified main images
|
||||
if: success() && gitea.ref == 'refs/heads/main'
|
||||
env:
|
||||
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
|
||||
REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: java generated/ci/Ci.java publish
|
||||
- name: Collect diagnostics and clean up test containers
|
||||
if: always()
|
||||
run: java generated/ci/Ci.java cleanup
|
||||
- name: Retain diagnostics for fourteen days
|
||||
if: always()
|
||||
uses: https://github.com/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
|
||||
with:
|
||||
name: diagnostics-${{ gitea.run_id }}-${{ env.CI_RUN_ATTEMPT }}
|
||||
path: ci/artifacts/
|
||||
if-no-files-found: error
|
||||
retention-days: 14
|
||||
70
templates/common/.gitea/workflows/deploy.yaml
Normal file
70
templates/common/.gitea/workflows/deploy.yaml
Normal file
@@ -0,0 +1,70 @@
|
||||
name: Deploy production
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
mode:
|
||||
description: 'Release mode'
|
||||
required: true
|
||||
type: choice
|
||||
default: new
|
||||
options:
|
||||
- new
|
||||
- retry
|
||||
increment:
|
||||
description: 'New release only: semantic version increment (first release is v1.0.0)'
|
||||
required: true
|
||||
type: choice
|
||||
default: patch
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
- major
|
||||
version:
|
||||
description: 'Retry only: existing version tag, e.g. v1.2.3; leave empty for new release'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
# Gitea 1.25 ignores concurrency. The helper acquires a NAS-wide mkdir lock.
|
||||
jobs:
|
||||
deploy:
|
||||
if: gitea.ref == 'refs/heads/main'
|
||||
runs-on: @RUNNER@
|
||||
env:
|
||||
CI: 'true'
|
||||
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
||||
CI_REPOSITORY: ${{ gitea.repository }}
|
||||
CI_COMMIT: ${{ gitea.sha }}
|
||||
CI_REF: ${{ gitea.ref }}
|
||||
CI_EVENT: ${{ gitea.event_name }}
|
||||
CI_RUN_ID: ${{ gitea.run_id }}
|
||||
steps:
|
||||
- name: Check out trusted main workflow revision
|
||||
uses: https://github.com/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Verify pinned engineering resources
|
||||
run: python3 scripts/engineering.py --check
|
||||
- name: Identify workflow attempt
|
||||
run: java generated/ci/Ci.java attempt
|
||||
- name: Release verified images
|
||||
env:
|
||||
RELEASE_MODE: ${{ inputs.mode }}
|
||||
RELEASE_INCREMENT: ${{ inputs.increment }}
|
||||
RELEASE_VERSION: ${{ inputs.version }}
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
DEPLOY_HOST: ${{ vars.DEPLOY_HOST }}
|
||||
DEPLOY_USER: ${{ vars.DEPLOY_USER }}
|
||||
DEPLOY_SSH_PORT: ${{ vars.DEPLOY_SSH_PORT }}
|
||||
DEPLOY_DIRECTORY: ${{ vars.DEPLOY_DIRECTORY }}
|
||||
DEPLOY_REGISTRY: ${{ vars.DEPLOY_REGISTRY }}
|
||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
DEPLOY_KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
|
||||
run: java generated/ci/Ci.java deploy
|
||||
- name: Retain deployment diagnostics for fourteen days
|
||||
if: always()
|
||||
uses: https://github.com/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
|
||||
with:
|
||||
name: deployment-${{ gitea.run_id }}-${{ env.CI_RUN_ATTEMPT }}
|
||||
path: ci/artifacts/deployment/
|
||||
if-no-files-found: warn
|
||||
retention-days: 14
|
||||
44
templates/common/.gitea/workflows/rollback.yaml
Normal file
44
templates/common/.gitea/workflows/rollback.yaml
Normal file
@@ -0,0 +1,44 @@
|
||||
name: Rollback production
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
rollback:
|
||||
if: gitea.ref == 'refs/heads/main'
|
||||
runs-on: @RUNNER@
|
||||
env:
|
||||
CI: 'true'
|
||||
GITEA_SERVER_URL: ${{ gitea.server_url }}
|
||||
CI_REPOSITORY: ${{ gitea.repository }}
|
||||
CI_COMMIT: ${{ gitea.sha }}
|
||||
CI_REF: ${{ gitea.ref }}
|
||||
CI_EVENT: ${{ gitea.event_name }}
|
||||
CI_RUN_ID: ${{ gitea.run_id }}
|
||||
steps:
|
||||
- name: Check out trusted main workflow revision
|
||||
uses: https://github.com/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Verify pinned engineering resources
|
||||
run: python3 scripts/engineering.py --check
|
||||
- name: Identify workflow attempt
|
||||
run: java generated/ci/Ci.java attempt
|
||||
- name: Restore previous successful release
|
||||
env:
|
||||
RELEASE_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
DEPLOY_HOST: ${{ vars.DEPLOY_HOST }}
|
||||
DEPLOY_USER: ${{ vars.DEPLOY_USER }}
|
||||
DEPLOY_SSH_PORT: ${{ vars.DEPLOY_SSH_PORT }}
|
||||
DEPLOY_DIRECTORY: ${{ vars.DEPLOY_DIRECTORY }}
|
||||
DEPLOY_REGISTRY: ${{ vars.DEPLOY_REGISTRY }}
|
||||
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
DEPLOY_KNOWN_HOSTS: ${{ secrets.DEPLOY_KNOWN_HOSTS }}
|
||||
run: java generated/ci/Ci.java rollback
|
||||
- name: Retain deployment diagnostics for fourteen days
|
||||
if: always()
|
||||
uses: https://github.com/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5
|
||||
with:
|
||||
name: rollback-${{ gitea.run_id }}-${{ env.CI_RUN_ATTEMPT }}
|
||||
path: ci/artifacts/deployment/
|
||||
if-no-files-found: warn
|
||||
retention-days: 14
|
||||
6
templates/common/.gitignore
vendored
Normal file
6
templates/common/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
target
|
||||
**/node_modules/
|
||||
**/dist/
|
||||
**/__pycache__/
|
||||
ci/artifacts/
|
||||
.env
|
||||
8
templates/common/AGENTS.md
Normal file
8
templates/common/AGENTS.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Project guidance
|
||||
|
||||
Read `generated/CODING_STANDARDS.md` before changing Java.
|
||||
For reviews use `generated/skills/code-review/SKILL.md` with
|
||||
`generated/docs/backend-review.md`.
|
||||
Specifications and ADRs: @LANDSCAPE@.
|
||||
Do not edit generated resources; use `mvn -N -Pregenerate-engineering validate`.
|
||||
See README.md for setup and engineering upgrades. Skills are project-local.
|
||||
20
templates/common/README.md
Normal file
20
templates/common/README.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# @PROJECT@
|
||||
|
||||
Generated from the version recorded in engineering.lock.json.
|
||||
Use JDK 25, Maven, Python 3, Git, Docker with Compose, and Node/npm for a frontend.
|
||||
Run `mvn verify` for a backend and `java generated/ci/Ci.java verify` for the full recipe.
|
||||
Local builds use committed generated files. Run
|
||||
`mvn -N -Pregenerate-engineering validate` to regenerate, or
|
||||
`python3 scripts/engineering.py --check` to check drift.
|
||||
|
||||
Edit engineering.properties for module paths, images (derived from PROJECT_NAME),
|
||||
deployment project, required secrets and dependencies. Edit deploy/health.sh for
|
||||
application readiness. Configure the workflow runner label and Gitea variables
|
||||
and secrets as described in the engineering README. Repository creation and
|
||||
secret installation are manual setup steps; the generator creates local files.
|
||||
|
||||
ADRs, specifications and onboarding: @LANDSCAPE@.
|
||||
Engineering usage and upgrades: @ENGINEERING@.
|
||||
Update engineering.lock.json's tag and commit together, regenerate and review
|
||||
the diff and that release's upgrade instructions. Project-owned files outside
|
||||
generated/ are never overwritten by an upgrade.
|
||||
11
templates/common/ci/runner/config.yaml
Normal file
11
templates/common/ci/runner/config.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
log:
|
||||
level: info
|
||||
runner:
|
||||
file: .runner
|
||||
capacity: 1
|
||||
timeout: 2h
|
||||
shutdown_timeout: 2m
|
||||
labels:
|
||||
- @RUNNER@:host
|
||||
cache:
|
||||
enabled: false
|
||||
3
templates/common/ci/runner/docker-daemon.json
Normal file
3
templates/common/ci/runner/docker-daemon.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"insecure-registries": ["192.168.2.28:3000"]
|
||||
}
|
||||
9
templates/common/ci/runner/docker-desktop.conf
Normal file
9
templates/common/ci/runner/docker-desktop.conf
Normal file
@@ -0,0 +1,9 @@
|
||||
# Desktop-specific override: start after graphical login, alongside Docker Desktop.
|
||||
[Unit]
|
||||
Requires=docker-desktop.service
|
||||
After=graphical-session.target docker-desktop.service
|
||||
PartOf=graphical-session.target docker-desktop.service
|
||||
|
||||
[Install]
|
||||
WantedBy=
|
||||
WantedBy=graphical-session.target
|
||||
19
templates/common/ci/runner/runner.service
Normal file
19
templates/common/ci/runner/runner.service
Normal file
@@ -0,0 +1,19 @@
|
||||
[Unit]
|
||||
Description=@PROJECT@ Gitea Actions runner
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
WorkingDirectory=%h/.local/share/@PROJECT@-runner
|
||||
EnvironmentFile=%h/.config/@PROJECT@-runner/environment
|
||||
ExecStartPre=/usr/bin/env java %h/.local/share/@PROJECT@-runner/WaitForDocker.java 120
|
||||
TimeoutStartSec=150
|
||||
ExecStart=%h/.local/bin/act_runner daemon --config %h/.local/share/@PROJECT@-runner/config.yaml
|
||||
Restart=on-failure
|
||||
RestartSec=10
|
||||
KillSignal=SIGTERM
|
||||
TimeoutStopSec=150
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
4
templates/common/deploy/health.sh
Normal file
4
templates/common/deploy/health.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
# Sourced by the shared deployment mechanism, retained with each release.
|
||||
application_health() {
|
||||
curl --noproxy '*' --fail --silent --show-error --max-time 5 "http://$BIND_IP:$FRONTEND_PORT/" -o /dev/null
|
||||
}
|
||||
6
templates/common/deploy/production.env.example
Normal file
6
templates/common/deploy/production.env.example
Normal file
@@ -0,0 +1,6 @@
|
||||
# Copy to the deployment directory as production.env, chmod 600; never commit real secrets.
|
||||
BIND_IP=127.0.0.1
|
||||
FRONTEND_PORT=8088
|
||||
DOCKER_BIN=/usr/bin/docker
|
||||
DOCKER_SUDO=0
|
||||
DOCKER_CONFIG=/absolute/deployment/path/docker-auth
|
||||
177
templates/common/pom.xml
Normal file
177
templates/common/pom.xml
Normal file
@@ -0,0 +1,177 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.example.@PROJECT@</groupId>
|
||||
<artifactId>@PROJECT@</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>@PROJECT@</name>
|
||||
<description>Generated engineering starter</description>
|
||||
|
||||
<modules>@MODULES@</modules>
|
||||
|
||||
<!-- TODO Add SCM ??? -->
|
||||
|
||||
<properties>
|
||||
<maven.compiler.release>25</maven.compiler.release>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<quarkus.platform.version>3.40.1</quarkus.platform.version>
|
||||
|
||||
<format.mode>apply</format.mode>
|
||||
<format.skip>false</format.skip>
|
||||
<palantir-java-format.version>2.101.0</palantir-java-format.version>
|
||||
<rewrite-core.version>8.63.4</rewrite-core.version>
|
||||
|
||||
<ortools-java.version>9.15.6755</ortools-java.version>
|
||||
<mapstruct.version>1.6.3</mapstruct.version>
|
||||
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
|
||||
<lombok.version>1.18.48</lombok.version>
|
||||
|
||||
<!-- test dependencies -->
|
||||
<archunit.version>1.5.1</archunit.version>
|
||||
<datafaker.version>2.7.0</datafaker.version>
|
||||
</properties>
|
||||
|
||||
<!-- dependencies that can be included by child-project - without stating the version -->
|
||||
<dependencyManagement><dependencies><dependency>
|
||||
<groupId>io.quarkus.platform</groupId><artifactId>quarkus-bom</artifactId><version>${quarkus.platform.version}</version><type>pom</type><scope>import</scope>
|
||||
</dependency></dependencies></dependencyManagement>
|
||||
|
||||
<!-- dependencies that will always be included by the child-project -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<version>3.6.3</version>
|
||||
<inherited>false</inherited>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>format</id>
|
||||
<phase>validate</phase>
|
||||
<goals><goal>exec</goal></goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<skip>${format.skip}</skip>
|
||||
<executable>${java.home}/bin/java</executable>
|
||||
<includeProjectDependencies>false</includeProjectDependencies>
|
||||
<includePluginDependencies>true</includePluginDependencies>
|
||||
<arguments>
|
||||
<argument>--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED</argument>
|
||||
<argument>--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</argument>
|
||||
<argument>--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</argument>
|
||||
<argument>--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</argument>
|
||||
<argument>--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</argument>
|
||||
<argument>--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</argument>
|
||||
<argument>--class-path</argument><classpath/>
|
||||
<argument>${maven.multiModuleProjectDirectory}/generated/tooling/format/Format.java</argument>
|
||||
<argument>${maven.multiModuleProjectDirectory}</argument>
|
||||
<argument>${format.mode}</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.palantir.javaformat</groupId>
|
||||
<artifactId>palantir-java-format</artifactId>
|
||||
<version>${palantir-java-format.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openrewrite</groupId>
|
||||
<artifactId>rewrite-core</artifactId>
|
||||
<version>${rewrite-core.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.16.0</version>
|
||||
<configuration>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
</systemPropertyVariables>
|
||||
<includes>
|
||||
<include>**/Test*.java</include>
|
||||
<include>**/*Test.java</include>
|
||||
<include>**/*Tests.java</include>
|
||||
<include>**/*TestCase.java</include>
|
||||
<include>**/*Sit.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-clean-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.5.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.5.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-install-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>regenerate-engineering</id>
|
||||
<properties><format.skip>true</format.skip></properties>
|
||||
<build><plugins><plugin>
|
||||
<groupId>org.codehaus.mojo</groupId><artifactId>exec-maven-plugin</artifactId><version>3.6.3</version>
|
||||
<inherited>false</inherited>
|
||||
<executions><execution><id>regenerate-engineering</id><phase>validate</phase><goals><goal>exec</goal></goals>
|
||||
<configuration combine.self="override"><executable>python3</executable>
|
||||
<arguments><argument>${maven.multiModuleProjectDirectory}/scripts/engineering.py</argument></arguments>
|
||||
</configuration>
|
||||
</execution></executions>
|
||||
</plugin></plugins></build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
Reference in New Issue
Block a user