demo-cicd seed

This commit is contained in:
seed
2026-09-17 16:08:32 +08:00
commit 41a6938873
13 changed files with 1535 additions and 0 deletions
Vendored
+99
View File
@@ -0,0 +1,99 @@
pipeline {
agent { label 'builder' }
options { timestamps(); disableConcurrentBuilds() }
environment { TAG = "b${env.BUILD_NUMBER}" }
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Maven') {
steps {
container('maven') {
withCredentials([usernamePassword(credentialsId: 'nexus-creds', usernameVariable: 'NU', passwordVariable: 'NP')]) {
sh '''#!/bin/sh -e
cat > settings.xml <<EOF
<settings>
<mirrors>
<mirror>
<id>nexus</id>
<mirrorOf>*</mirrorOf>
<url>https://nexus.otone.run/repository/maven-central/</url>
</mirror>
</mirrors>
<servers>
<server>
<id>nexus-releases</id>
<username>${NU}</username>
<password>${NP}</password>
</server>
</servers>
</settings>
EOF
cd backend-maven
mvn -s ../settings.xml -B -q -Drevision=1.0.$BUILD_NUMBER deploy
'''
}
}
}
}
stage('Gradle') {
steps {
container('gradle') {
withCredentials([usernamePassword(credentialsId: 'nexus-creds', usernameVariable: 'NU', passwordVariable: 'NP')]) {
sh 'cd backend-gradle && gradle --no-daemon -q publish -PnexusUser=$NU -PnexusPass=$NP'
}
}
}
}
stage('Frontend') {
steps {
container('node') {
withCredentials([usernamePassword(credentialsId: 'nexus-creds', usernameVariable: 'NU', passwordVariable: 'NP')]) {
sh '''#!/bin/sh -e
cd frontend
echo "registry=https://nexus.otone.run/repository/npm-proxy/" > .npmrc
npm ci
npm run build
cd pkg
npm version 1.0.$BUILD_NUMBER --allow-same-version --no-git-tag-version
printf '//nexus.otone.run/repository/npm-hosted/:_auth=%s\nregistry=https://nexus.otone.run/repository/npm-hosted/\n' "$(printf '%s:%s' "$NU" "$NP" | base64)" > .npmrc
npm publish
'''
}
}
}
}
stage('Image') {
steps {
container('kaniko') {
withCredentials([usernamePassword(credentialsId: 'harbor-creds', usernameVariable: 'HU', passwordVariable: 'HP')]) {
sh '''#!/busybox/sh -e
mkdir -p /kaniko/.docker
printf '{"auths":{"harbor.otone.run":{"auth":"%s"}}}' "$(printf '%s:%s' "$HU" "$HP" | base64 | tr -d '\n')" > /kaniko/.docker/config.json
/kaniko/executor --context $WORKSPACE --dockerfile docker/backend.Dockerfile --destination harbor.otone.run/otone/demo-api:$TAG --cleanup
/kaniko/executor --context $WORKSPACE --dockerfile docker/frontend.Dockerfile --destination harbor.otone.run/otone/demo-web:$TAG --cleanup
'''
}
}
}
}
stage('Deploy') {
steps {
container('kubectl') {
withCredentials([file(credentialsId: 'kubeconfig', variable: 'KC')]) {
sh 'sed "s/__TAG__/$TAG/g" k8s.yaml | kubectl --kubeconfig $KC apply -f -'
}
}
}
}
stage('Verify') {
steps {
container('maven') {
retry(10) {
sh 'sleep 6; curl -sf https://demo.otone.run/ >/dev/null && curl -sf https://demo-api.otone.run/ >/dev/null && echo ALL-GREEN'
}
}
}
}
}
}
+16
View File
@@ -0,0 +1,16 @@
plugins { id 'java-library'; id 'maven-publish' }
group = 'com.otone.demo'
version = "1.0.${System.getenv('BUILD_NUMBER') ?: '0'}"
repositories { maven { url = 'https://nexus.otone.run/repository/maven-central/' } }
publishing {
repositories {
maven {
url = 'https://nexus.otone.run/repository/maven-releases/'
credentials {
username = findProperty('nexusUser')
password = findProperty('nexusPass')
}
}
}
publications { maven(MavenPublication) { from components.java } }
}
@@ -0,0 +1,4 @@
package com.otone.demo;
public class Greet {
public static String greet(String name) { return "hi " + name; }
}
+58
View File
@@ -0,0 +1,58 @@
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.otone.demo</groupId>
<artifactId>demo-api</artifactId>
<version>${revision}</version>
<packaging>jar</packaging>
<properties>
<revision>1.0.0</revision>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
</dependencies>
<build>
<finalName>demo-api</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<archive><manifest><mainClass>com.otone.demo.Api</mainClass></manifest></archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.3</version>
<executions>
<execution>
<phase>package</phase>
<goals><goal>shade</goal></goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.otone.demo.Api</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<distributionManagement>
<repository>
<id>nexus-releases</id>
<url>https://nexus.otone.run/repository/maven-releases/</url>
</repository>
</distributionManagement>
</project>
@@ -0,0 +1,18 @@
package com.otone.demo;
import com.sun.net.httpserver.HttpServer;
import org.apache.commons.lang3.StringUtils;
public class Api {
public static void main(String[] args) throws Exception {
HttpServer s = HttpServer.create(new java.net.InetSocketAddress(8080), 0);
s.createContext("/", ex -> {
String body = "hello from " + StringUtils.capitalize("demo-api");
ex.sendResponseHeaders(200, body.getBytes().length);
ex.getResponseBody().write(body.getBytes());
ex.close();
});
s.start();
System.out.println("demo-api listening :8080");
}
}
+3
View File
@@ -0,0 +1,3 @@
FROM docker.m.daocloud.io/library/eclipse-temurin:21-jre-alpine
COPY backend-maven/target/demo-api.jar /app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
+2
View File
@@ -0,0 +1,2 @@
FROM docker.m.daocloud.io/library/nginx:alpine
COPY frontend/dist /usr/share/nginx/html
+3
View File
@@ -0,0 +1,3 @@
<!doctype html>
<html><head><meta charset="utf-8"><title>demo</title></head>
<body><div id="app"></div><script type="module" src="/src/main.js"></script></body></html>
+1250
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
{
"name": "demo-web",
"private": true,
"version": "1.0.0",
"scripts": { "build": "vite build" },
"dependencies": { "vue": "^3.4.0" },
"devDependencies": { "vite": "^5.2.0" }
}
+5
View File
@@ -0,0 +1,5 @@
{
"name": "@otone/demo-ui-utils",
"version": "1.0.0",
"description": "demo package published to nexus npm-hosted"
}
+2
View File
@@ -0,0 +1,2 @@
import { createApp, h } from 'vue'
createApp({ render: () => h('h1', 'demo-web CI/CD OK') }).mount('#app')
+67
View File
@@ -0,0 +1,67 @@
apiVersion: apps/v1
kind: Deployment
metadata: {name: demo-api, namespace: devops}
spec:
replicas: 1
selector: {matchLabels: {app: demo-api}}
template:
metadata: {labels: {app: demo-api}}
spec:
containers:
- name: demo-api
image: harbor.otone.run/otone/demo-api:__TAG__
ports: [{containerPort: 8080}]
resources: {requests: {memory: 128Mi}, limits: {memory: 512Mi}}
---
apiVersion: v1
kind: Service
metadata: {name: demo-api, namespace: devops}
spec:
selector: {app: demo-api}
ports: [{port: 8080, targetPort: 8080}]
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: demo-web, namespace: devops}
spec:
replicas: 1
selector: {matchLabels: {app: demo-web}}
template:
metadata: {labels: {app: demo-web}}
spec:
containers:
- name: demo-web
image: harbor.otone.run/otone/demo-web:__TAG__
ports: [{containerPort: 80}]
resources: {requests: {memory: 64Mi}, limits: {memory: 256Mi}}
---
apiVersion: v1
kind: Service
metadata: {name: demo-web, namespace: devops}
spec:
selector: {app: demo-web}
ports: [{port: 80, targetPort: 80}]
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo
namespace: devops
spec:
ingressClassName: traefik
rules:
- host: demo.otone.run
http:
paths:
- path: /
pathType: Prefix
backend: {service: {name: demo-web, port: {number: 80}}}
- host: demo-api.otone.run
http:
paths:
- path: /
pathType: Prefix
backend: {service: {name: demo-api, port: {number: 8080}}}
tls:
- hosts: [demo.otone.run, demo-api.otone.run]
secretName: otone-tls