forked from jk_yinzy/cicd-test
Compare commits
115 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2251b1c1df | |||
| d527e8d5cd | |||
| 0d9ca2802a | |||
|
|
3d0a5decef | ||
| 7833a33563 | |||
|
|
c17a305892 | ||
|
|
a19e8d933b | ||
| ee40798b8d | |||
|
|
b477da7a88 | ||
| 0dd1dd5420 | |||
|
|
b642fc0642 | ||
| 2e670b15f9 | |||
|
|
902ae891d8 | ||
| dda1763ce6 | |||
|
|
4da446dfc3 | ||
|
|
5ddbcb87e9 | ||
| 9bf3aba2ae | |||
|
|
f7acb824b6 | ||
| 8e78104fb5 | |||
|
|
1da65bf24f | ||
|
|
b6d4197d1f | ||
| f167105696 | |||
|
|
bac64704f7 | ||
| fa8c144290 | |||
|
|
a14728d961 | ||
| 07e1651a40 | |||
|
|
a311d1588c | ||
| 47145fe318 | |||
|
|
175d58c97a | ||
| ba69ce8f4a | |||
|
|
23946e72eb | ||
|
|
e4d30d38fb | ||
| adb6aaff3f | |||
|
|
d1f4552574 | ||
| 6103344938 | |||
|
|
b79fb4e5f4 | ||
|
|
9e95b0d608 | ||
|
|
e28f963c01 | ||
|
|
f1b158889d | ||
|
|
28048bd30e | ||
|
|
126ca08ed5 | ||
|
|
f9c4157d32 | ||
|
|
e6e78fa287 | ||
|
|
705d2141b7 | ||
|
|
5db414093e | ||
| 8ccf1dd2c3 | |||
|
|
686b838fba | ||
|
|
cf5c39464c | ||
|
|
0f993b9dbb | ||
| 8fa022008e | |||
|
|
5a8551fed2 | ||
| 2e114d4070 | |||
|
|
fe8468ae43 | ||
| 96e47681e7 | |||
|
|
2c06d69e45 | ||
| 1990a9e970 | |||
|
|
bc014933a4 | ||
| f70beb3179 | |||
|
|
63dffbc4ac | ||
| a2fec3b29d | |||
|
|
76ba747874 | ||
| a056cd5798 | |||
|
|
a74ae4d400 | ||
| fb342e26b1 | |||
|
|
1e8c2e0d74 | ||
| 8e739da04c | |||
|
|
38092b3537 | ||
| 172f9b8229 | |||
|
|
7a0289903e | ||
| 81308c28f4 | |||
|
|
3af0f97175 | ||
| 996b7db539 | |||
|
|
bc663d5e88 | ||
| 3dac3b6246 | |||
|
|
00bde2e706 | ||
| bcdf49f72e | |||
|
|
0153a376b6 | ||
|
|
8264c16dbf | ||
|
|
10e0d033ef | ||
|
|
3f2a5226c8 | ||
| af67f1bbe3 | |||
|
|
dd740e5e98 | ||
| dcdeaba664 | |||
|
|
043e65249a | ||
| 55cfa56e91 | |||
|
|
2ec8bacad3 | ||
| 57d1badb9a | |||
|
|
7fa2eb8bd9 | ||
|
|
7813b0dbb9 | ||
| e2ee130797 | |||
|
|
c122d8e8ac | ||
| f3ba3c0cc0 | |||
|
|
f030dcdd9d | ||
| ade6a53e1d | |||
|
|
1ac3f504d5 | ||
| 2d1cb2d03e | |||
|
|
d00fd20c3f | ||
|
|
768ea01ea1 | ||
|
|
a5c24fc31a | ||
|
|
99bf38c9ff | ||
|
|
067aad30df | ||
|
|
ad7f4e9672 | ||
|
|
63c98c5eb1 | ||
|
|
fdf48941ee | ||
|
|
d44e7d386f | ||
|
|
700f59cfaf | ||
|
|
23f1ed19b2 | ||
|
|
006c3c6643 | ||
|
|
b328ad6d07 | ||
|
|
e54b9750ae | ||
|
|
fbb6d9f48b | ||
| c7c01ddc21 | |||
| ee6c8ec6a5 | |||
| 102f5ca8f0 | |||
| b5b5d1e299 |
308
.drone.yml
308
.drone.yml
@ -1,69 +1,293 @@
|
|||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: docker
|
type: docker
|
||||||
name: multi-lang-ci
|
name: pr-ci
|
||||||
|
|
||||||
|
# PR 流水线:仅在 PR 触发
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
branch:
|
# 如需限制目标分支,可加 target:
|
||||||
- main
|
# target:
|
||||||
|
# - main
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
base: /drone
|
||||||
|
path: .
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: maven-cache
|
||||||
|
path: /localcache/maven/repository
|
||||||
|
- name: npm-cache
|
||||||
|
path: /localcache/npm-cache
|
||||||
|
|
||||||
# 克隆策略:只拉最新 commit,加速
|
|
||||||
clone:
|
clone:
|
||||||
depth: 0
|
depth: 0
|
||||||
image: drone/git:latest
|
image: drone/git:latest
|
||||||
pull: false
|
pull: false
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# 自动检测是否存在 Java (pom.xml)
|
- name: java-build-test
|
||||||
- name: java-build
|
image: registry.cn-beijing.aliyuncs.com/yinzy/maven:jk3.9-8
|
||||||
image: maven:3.9-eclipse-temurin
|
|
||||||
pull: false
|
pull: false
|
||||||
|
volumes:
|
||||||
|
- name: maven-cache
|
||||||
|
path: /localcache/maven/repository
|
||||||
environment:
|
environment:
|
||||||
MAVEN_OPTS: -Dmaven.repo.local=.m2/repository
|
MAVEN_OPTS: -Dmaven.repo.local=/localcache/maven/repository
|
||||||
commands:
|
commands:
|
||||||
# 先创建 .m2 目录
|
# - touch /localcache/maven/repository/bbb.txt
|
||||||
|
# - ls -lah /localcache/maven/repository
|
||||||
- mkdir -p ~/.m2
|
- mkdir -p ~/.m2
|
||||||
# 动态生成 settings.xml(仅用于 CI)
|
- cat ~/.m2/settings.xml
|
||||||
- |
|
- mvn -B clean test package
|
||||||
cat > ~/.m2/settings.xml << 'EOF'
|
- ls -lah target/*.jar || (echo "JAR file not found!" && exit 1)
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
- \cp target/*.jar ./ -f
|
||||||
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
|
|
||||||
<mirrors>
|
|
||||||
<mirror>
|
|
||||||
<id>aliyun</id>
|
|
||||||
<mirrorOf>*</mirrorOf>
|
|
||||||
<name>Aliyun Maven</name>
|
|
||||||
<url>https://maven.aliyun.com/repository/public</url>
|
|
||||||
</mirror>
|
|
||||||
</mirrors>
|
|
||||||
</settings>
|
|
||||||
EOF
|
|
||||||
- mvn clean verify
|
|
||||||
- if [ -f pom.xml ]; then mvn clean compile; fi
|
|
||||||
when:
|
|
||||||
event: [ push, pull_request ]
|
|
||||||
|
|
||||||
# 自动检测是否存在 Python (requirements.txt)
|
- name: frontend-build
|
||||||
- name: python-test
|
image: registry.cn-beijing.aliyuncs.com/yinzy/node:20.11-alpine3.19
|
||||||
image: python:3.12.0-slim
|
|
||||||
pull: false
|
pull: false
|
||||||
|
volumes:
|
||||||
|
- name: npm-cache
|
||||||
|
path: /localcache/npm-cache
|
||||||
commands:
|
commands:
|
||||||
# 临时设置 pip 源(仅本次会话)
|
- cd vue-ui
|
||||||
- pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple/
|
- npm config set cache /localcache/npm-cache/.npm
|
||||||
- pip config set install.trusted-host pypi.tuna.tsinghua.edu.cn
|
- npm ci -prefer-offline --registry=https://registry.npmmirror.com
|
||||||
- if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
- npm run build
|
||||||
- if [ -f test_example.py ]; then python -m pytest test_example.py -v; fi
|
- ls -lah dist
|
||||||
when:
|
|
||||||
event: [ push, pull_request ]
|
|
||||||
|
|
||||||
# 最终报告(无论成功失败都运行)
|
# 如需其他检查步骤,可在这里继续追加
|
||||||
- name: summary
|
- name: summary
|
||||||
image: alpine
|
image: alpine
|
||||||
pull: false
|
pull: false
|
||||||
commands:
|
commands:
|
||||||
- echo "✅ CI completed at $(date)"
|
- echo "✅ PR pipeline completed at $(date)"
|
||||||
when:
|
when:
|
||||||
status: [ success, failure ]
|
status: [ success, failure ]
|
||||||
|
depends_on:
|
||||||
|
- java-build-test
|
||||||
|
- frontend-build
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
kind: pipeline
|
||||||
|
type: docker
|
||||||
|
name: release-tag
|
||||||
|
|
||||||
|
# Tag 流水线:仅在 tag 触发(不要加 branch 限制)
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- tag
|
||||||
|
branch:
|
||||||
|
- "**"
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
base: /drone
|
||||||
|
path: .
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
- name: maven-cache
|
||||||
|
path: /localcache/maven/repository
|
||||||
|
- name: docker_sock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
- name: jar-cache
|
||||||
|
path: /localcache/apps
|
||||||
|
- name: npm-cache
|
||||||
|
path: /localcache/npm-cache
|
||||||
|
- name: certs
|
||||||
|
path: /localcache/registry_certs # 你提前放好 ca.crt
|
||||||
|
|
||||||
|
clone:
|
||||||
|
depth: 0
|
||||||
|
image: drone/git:latest
|
||||||
|
pull: false
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: frontend-build
|
||||||
|
image: registry.cn-beijing.aliyuncs.com/yinzy/node:20.11-alpine3.19
|
||||||
|
pull: false
|
||||||
|
volumes:
|
||||||
|
- name: npm-cache
|
||||||
|
path: /localcache/npm-cache
|
||||||
|
- name: jar-cache # 复用已有 /localcache,用于暂存 dist.zip
|
||||||
|
path: /localcache/apps
|
||||||
|
commands:
|
||||||
|
- cd vue-ui
|
||||||
|
- npm config set cache /localcache/npm-cache/.npm
|
||||||
|
- npm ci -prefer-offline --registry=https://registry.npmmirror.com
|
||||||
|
- npm run build
|
||||||
|
- cd dist && tar -czf ../dist.tgz . && cd ..
|
||||||
|
- mkdir -p /localcache/apps/${DRONE_REPO_NAME}
|
||||||
|
- cp dist.tgz /localcache/apps/${DRONE_REPO_NAME}/dist-${DRONE_TAG}.tgz -f && cp dist.tgz ../ -f
|
||||||
|
- ls -lah /localcache/apps/${DRONE_REPO_NAME}/dist-${DRONE_TAG}.tgz
|
||||||
|
# - cd ../ && ls -lah vue-ui/dist.tgz
|
||||||
|
|
||||||
|
- name: java-build
|
||||||
|
image: registry.cn-beijing.aliyuncs.com/yinzy/maven:jk3.9-8
|
||||||
|
pull: false
|
||||||
|
volumes:
|
||||||
|
- name: maven-cache
|
||||||
|
path: /localcache/maven/repository
|
||||||
|
- name: jar-cache
|
||||||
|
path: /localcache/apps
|
||||||
|
environment:
|
||||||
|
MAVEN_OPTS: -Dmaven.repo.local=/localcache/maven/repository
|
||||||
|
commands:
|
||||||
|
- mvn -B -DskipTests=true clean package
|
||||||
|
- ls -lah target/*.jar || (echo "JAR file not found!" && exit 1)
|
||||||
|
- |
|
||||||
|
mkdir -p /localcache/apps/${DRONE_REPO_NAME}
|
||||||
|
JAR_FILE=$(ls target/*.jar 2>/dev/null | head -1)
|
||||||
|
if [ -n "$JAR_FILE" ]; then
|
||||||
|
cp "$JAR_FILE" /localcache/apps/${DRONE_REPO_NAME}/ -f
|
||||||
|
echo "✅ JAR file backed up to /localcache/apps/${DRONE_REPO_NAME}/$(basename $JAR_FILE)"
|
||||||
|
ls -lh /localcache/apps/${DRONE_REPO_NAME}/
|
||||||
|
else
|
||||||
|
echo "⚠️ No JAR file found to backup"
|
||||||
|
fi
|
||||||
|
#
|
||||||
|
# - name: debug_context
|
||||||
|
# image: alpine
|
||||||
|
# commands:
|
||||||
|
# - pwd
|
||||||
|
# - ls -R .
|
||||||
|
# depends_on:
|
||||||
|
# - frontend-build
|
||||||
|
|
||||||
|
- name: frontend_docker_build
|
||||||
|
image: registry.cn-beijing.aliyuncs.com/yinzy/drone-plugins:docker-latest
|
||||||
|
pull: false
|
||||||
|
settings:
|
||||||
|
volumes:
|
||||||
|
- name: certs
|
||||||
|
path: /etc/docker/certs.d/docker-registry.local:36000/
|
||||||
|
debug: true
|
||||||
|
daemon_off: false # 👈 必须启用 DinD 才能让 extra_files 生效
|
||||||
|
# 1. 仓库认证信息
|
||||||
|
registry:
|
||||||
|
from_secret: local_registry_base_url
|
||||||
|
username:
|
||||||
|
from_secret: local_registry_user
|
||||||
|
password:
|
||||||
|
from_secret: local_registry_pass
|
||||||
|
|
||||||
|
# 2. 镜像名称 (不包含 Tag)
|
||||||
|
repo: docker-registry.local:36000/jk/apps/${DRONE_REPO_NAME}-front
|
||||||
|
|
||||||
|
# 3. 指定 Dockerfile 位置
|
||||||
|
dockerfile: docker/Dockerfile-frontend
|
||||||
|
|
||||||
|
# 4. 构建上下文 (Context),默认为 . (根目录)
|
||||||
|
context: .
|
||||||
|
|
||||||
|
# 5. 生成的 Tags
|
||||||
|
# 插件会自动生成 repo:tag
|
||||||
|
tags:
|
||||||
|
- front-${DRONE_TAG} # e.g. back-v1.0.0
|
||||||
|
- front-latest # 方便随时拉取最新版
|
||||||
|
# - front-${DRONE_COMMIT_SHA:0:8}
|
||||||
|
# 如果你需要把 dist.tgz 复制给 build
|
||||||
|
extra_files:
|
||||||
|
- dist.tgz
|
||||||
|
depends_on:
|
||||||
|
- frontend-build
|
||||||
|
# - debug_context
|
||||||
|
|
||||||
|
- name: backend_docker_build
|
||||||
|
image: registry.cn-beijing.aliyuncs.com/yinzy/drone-plugins:docker-latest
|
||||||
|
pull: false
|
||||||
|
settings:
|
||||||
|
volumes:
|
||||||
|
- name: certs
|
||||||
|
path: /etc/docker/certs.d/docker-registry.local:36000/
|
||||||
|
debug: true
|
||||||
|
daemon_off: false # 👈 必须启用 DinD 才能让 extra_files 生效
|
||||||
|
# 1. 仓库认证信息
|
||||||
|
registry:
|
||||||
|
from_secret: local_registry_base_url
|
||||||
|
username:
|
||||||
|
from_secret: local_registry_user
|
||||||
|
password:
|
||||||
|
from_secret: local_registry_pass
|
||||||
|
|
||||||
|
# 2. 镜像名称 (不包含 Tag)
|
||||||
|
repo: docker-registry.local:36000/jk/apps/${DRONE_REPO_NAME}-backend
|
||||||
|
|
||||||
|
# 3. 指定 Dockerfile 位置
|
||||||
|
dockerfile: docker/Dockerfile
|
||||||
|
|
||||||
|
# 4. 构建上下文 (Context),默认为 . (根目录)
|
||||||
|
context: .
|
||||||
|
|
||||||
|
# 5. 生成的 Tags
|
||||||
|
tags:
|
||||||
|
- backend-${DRONE_TAG} # e.g. back-v1.0.0
|
||||||
|
- backend-latest # 方便随时拉取最新版
|
||||||
|
extra_files:
|
||||||
|
- drone-test-1.0.jar
|
||||||
|
depends_on:
|
||||||
|
- java-build
|
||||||
|
|
||||||
|
- name: gitea_release
|
||||||
|
image: registry.cn-beijing.aliyuncs.com/yinzy/drone-plugins:gitea-release-latest
|
||||||
|
pull: false
|
||||||
|
volumes:
|
||||||
|
- name: jar-cache
|
||||||
|
path: /localcache/apps
|
||||||
|
settings:
|
||||||
|
api_key:
|
||||||
|
from_secret: gitea_token
|
||||||
|
base_url:
|
||||||
|
from_secret: gitea_base_url
|
||||||
|
files:
|
||||||
|
- /localcache/apps/${DRONE_REPO_NAME}/*.jar
|
||||||
|
- /localcache/apps/${DRONE_REPO_NAME}/dist-${DRONE_TAG}.tgz
|
||||||
|
title: Release ${DRONE_TAG}
|
||||||
|
note: |
|
||||||
|
Release ${DRONE_TAG}
|
||||||
|
|
||||||
|
Commit: ${DRONE_COMMIT_SHA:0:8}
|
||||||
|
Build: ${DRONE_BUILD_NUMBER}
|
||||||
|
file_exists: overwrite
|
||||||
|
depends_on:
|
||||||
|
- backend_docker_build
|
||||||
|
- frontend_docker_build
|
||||||
|
|
||||||
|
- name: push_acr
|
||||||
|
image: docker:latest
|
||||||
|
pull: false
|
||||||
|
volumes:
|
||||||
|
- name: docker_sock
|
||||||
|
path: /var/run/docker.sock
|
||||||
|
environment:
|
||||||
|
ACR_USER:
|
||||||
|
from_secret: aliyun_acr_username # 阿里云访问凭证用户名
|
||||||
|
ACR_PASS:
|
||||||
|
from_secret: aliyun_acr_password # 阿里云访问凭证密码
|
||||||
|
ACR_REGISTRY: registry.cn-beijing.aliyuncs.com
|
||||||
|
ACR_NAMESPACE: yinzy
|
||||||
|
ACR_REPO: cicd
|
||||||
|
commands:
|
||||||
|
- echo "$ACR_PASS" | docker login $ACR_REGISTRY -u "$ACR_USER" --password-stdin
|
||||||
|
# 后端
|
||||||
|
- docker tag ${DRONE_REPO_NAME}:latest $ACR_REGISTRY/$ACR_NAMESPACE/$ACR_REPO:back-${DRONE_TAG}
|
||||||
|
- docker push $ACR_REGISTRY/$ACR_NAMESPACE/$ACR_REPO:back-${DRONE_TAG}
|
||||||
|
# 前端
|
||||||
|
- docker tag ${DRONE_REPO_NAME}-frontend:latest $ACR_REGISTRY/$ACR_NAMESPACE/$ACR_REPO:front-${DRONE_TAG}
|
||||||
|
- docker push $ACR_REGISTRY/$ACR_NAMESPACE/$ACR_REPO:front-${DRONE_TAG}
|
||||||
|
depends_on:
|
||||||
|
- backend_docker_build
|
||||||
|
- frontend_docker_build
|
||||||
|
when:
|
||||||
|
event:
|
||||||
|
exclude: [ "**" ]
|
||||||
|
|
||||||
|
- name: summary
|
||||||
|
image: alpine
|
||||||
|
pull: false
|
||||||
|
commands:
|
||||||
|
- echo "✅ Tag pipeline completed at $(date)"
|
||||||
|
when:
|
||||||
|
status: [ success, failure ]
|
||||||
|
depends_on:
|
||||||
|
- gitea_release
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -26,3 +26,6 @@ replay_pid*
|
|||||||
|
|
||||||
/drone-test.iml
|
/drone-test.iml
|
||||||
/.idea/
|
/.idea/
|
||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
/.vscode/
|
||||||
|
|||||||
11
docker/Dockerfile
Normal file
11
docker/Dockerfile
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 使用最小的 Java 8 JRE 镜像
|
||||||
|
FROM docker-registry.local:36000/base/openjdk:8-jre-alpine
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 复制生成的 JAR 文件到容器中(使用通配符匹配)
|
||||||
|
COPY target/*.jar app.jar
|
||||||
|
|
||||||
|
# 运行应用
|
||||||
|
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||||
29
docker/Dockerfile-frontend
Normal file
29
docker/Dockerfile-frontend
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# 前端构建阶段
|
||||||
|
FROM docker-registry.local:36000/base/node:20.11-alpine3.19 AS builder
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 先复制依赖声明,利用缓存
|
||||||
|
COPY vue-ui/package*.json ./
|
||||||
|
|
||||||
|
# 使用国内镜像源并安装依赖
|
||||||
|
# RUN npm config set registry https://registry.npmmirror.com \
|
||||||
|
# && npm ci --no-audit --no-fund
|
||||||
|
|
||||||
|
# 复制源码并构建
|
||||||
|
COPY vue-ui/ .
|
||||||
|
# RUN npm run build
|
||||||
|
|
||||||
|
# 运行阶段,使用独立 nginx 镜像
|
||||||
|
FROM docker-registry.local:36000/base/nginx:alpine-stable AS runtime
|
||||||
|
|
||||||
|
# 清理默认页面
|
||||||
|
WORKDIR /usr/share/nginx/html
|
||||||
|
RUN rm -rf ./*
|
||||||
|
|
||||||
|
# 拷贝构建产物
|
||||||
|
# 直接使用构建上下文中的 dist.tgz
|
||||||
|
ADD dist.tgz .
|
||||||
|
|
||||||
|
EXPOSE 80
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
60
pom.xml
60
pom.xml
@ -7,10 +7,14 @@
|
|||||||
<groupId>com.example</groupId>
|
<groupId>com.example</groupId>
|
||||||
<artifactId>drone-test</artifactId>
|
<artifactId>drone-test</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.0</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.junit.jupiter</groupId>
|
<groupId>org.junit.jupiter</groupId>
|
||||||
@ -19,4 +23,56 @@
|
|||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<!-- Maven 编译插件 -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>8</source>
|
||||||
|
<target>8</target>
|
||||||
|
<encoding>UTF-8</encoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Maven JAR 插件,用于生成可执行 JAR -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.2.0</version>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>com.example.App</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!-- Maven Shade 插件,用于生成包含所有依赖的可执行 JAR(可选) -->
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.2.4</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>com.example.App</mainClass>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
</project>
|
</project>
|
||||||
@ -9,4 +9,4 @@ def test_drone_env():
|
|||||||
assert 'DRONE' in os.environ # 验证是否在 Drone 环境中运行
|
assert 'DRONE' in os.environ # 验证是否在 Drone 环境中运行
|
||||||
|
|
||||||
def test_1():
|
def test_1():
|
||||||
print("本地开发分支提交")
|
print("本地开发分支提交!s")
|
||||||
12
vue-ui/index.html
Normal file
12
vue-ui/index.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vue UI Demo</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1162
vue-ui/package-lock.json
generated
Normal file
1162
vue-ui/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
18
vue-ui/package.json
Normal file
18
vue-ui/package.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "vue-ui",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"vue": "^3.4.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@vitejs/plugin-vue": "^5.0.0",
|
||||||
|
"vite": "^5.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
89
vue-ui/src/App.vue
Normal file
89
vue-ui/src/App.vue
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
<template>
|
||||||
|
<main class="page">
|
||||||
|
<header class="hero">
|
||||||
|
<p class="eyebrow">Vue 3 + Vite</p>
|
||||||
|
<h1>快速上手示例</h1>
|
||||||
|
<p class="sub">
|
||||||
|
左边计数器,右边简单待办。直接改这里即可开始玩。
|
||||||
|
</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<section class="grid">
|
||||||
|
<article class="card">
|
||||||
|
<header class="card__title">
|
||||||
|
<h2>计数器</h2>
|
||||||
|
<span class="tag">可组合</span>
|
||||||
|
</header>
|
||||||
|
<p class="value">{{ count }}</p>
|
||||||
|
<div class="actions">
|
||||||
|
<button class="ghost" @click="change(-1)">-1</button>
|
||||||
|
<button class="primary" @click="change(1)">+1</button>
|
||||||
|
<button class="ghost" @click="reset">重置</button>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="card">
|
||||||
|
<header class="card__title">
|
||||||
|
<h2>待办清单</h2>
|
||||||
|
<span class="tag success">示例</span>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<form class="todo__form" @submit.prevent="addTodo">
|
||||||
|
<input
|
||||||
|
v-model="draft"
|
||||||
|
type="text"
|
||||||
|
placeholder="输入要做的事..."
|
||||||
|
autocomplete="off"
|
||||||
|
/>
|
||||||
|
<button class="primary" type="submit">添加</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<ul class="todo__list" v-if="todos.length">
|
||||||
|
<li v-for="item in todos" :key="item.id">
|
||||||
|
<label>
|
||||||
|
<input v-model="item.done" type="checkbox" />
|
||||||
|
<span :class="{ done: item.done }">{{ item.text }}</span>
|
||||||
|
</label>
|
||||||
|
<button class="ghost small" type="button" @click="removeTodo(item.id)">
|
||||||
|
删除
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<p v-else class="empty">暂无任务,添加一个吧!</p>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
|
||||||
|
const count = ref(1);
|
||||||
|
const change = (delta) => {
|
||||||
|
count.value += delta;
|
||||||
|
};
|
||||||
|
const reset = () => {
|
||||||
|
count.value = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const draft = ref('');
|
||||||
|
const todos = ref([
|
||||||
|
{ id: 1, text: '试着勾选或删除我', done: false },
|
||||||
|
{ id: 2, text: '在右上角编辑样式', done: true },
|
||||||
|
]);
|
||||||
|
|
||||||
|
const addTodo = () => {
|
||||||
|
const text = draft.value.trim();
|
||||||
|
if (!text) return;
|
||||||
|
todos.value.push({
|
||||||
|
id: Date.now(),
|
||||||
|
text,
|
||||||
|
done: false,
|
||||||
|
});
|
||||||
|
draft.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeTodo = (id) => {
|
||||||
|
todos.value = todos.value.filter((item) => item.id !== id);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
196
vue-ui/src/assets/main.css
Normal file
196
vue-ui/src/assets/main.css
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
:root {
|
||||||
|
font-family: 'Inter', 'PingFang SC', 'Microsoft YaHei', system-ui, -apple-system,
|
||||||
|
BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
||||||
|
color: #0f172a;
|
||||||
|
background-color: #f8fafc;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: radial-gradient(circle at top right, #e0f2fe, #f8fafc 45%),
|
||||||
|
radial-gradient(circle at 20% 20%, #f1f5f9, #f8fafc 45%);
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
max-width: 960px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 48px 20px 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero {
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.eyebrow {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 999px;
|
||||||
|
background-color: #e0f2fe;
|
||||||
|
color: #0284c7;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 12px;
|
||||||
|
letter-spacing: 0.04em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 12px 0 8px;
|
||||||
|
font-size: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub {
|
||||||
|
margin: 0;
|
||||||
|
color: #475569;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card__title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
padding: 4px 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background-color: #e2e8f0;
|
||||||
|
color: #475569;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag.success {
|
||||||
|
background-color: #dcfce7;
|
||||||
|
color: #16a34a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-size: 48px;
|
||||||
|
font-weight: 800;
|
||||||
|
margin: 0 0 16px;
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border: none;
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: 700;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.1s ease, box-shadow 0.2s ease, background 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:active {
|
||||||
|
transform: translateY(1px);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.primary {
|
||||||
|
background: linear-gradient(135deg, #22c55e, #16a34a);
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: 0 8px 20px rgba(22, 163, 74, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.ghost {
|
||||||
|
background: #f1f5f9;
|
||||||
|
color: #0f172a;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.small {
|
||||||
|
padding: 6px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo__form {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo__form input {
|
||||||
|
padding: 12px 14px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 12px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo__list {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo__list li {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 12px;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo__list label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
color: #0f172a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.todo__list input[type='checkbox'] {
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.done {
|
||||||
|
text-decoration: line-through;
|
||||||
|
color: #94a3b8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
margin: 0;
|
||||||
|
color: #94a3b8;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
.page {
|
||||||
|
padding: 32px 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 26px;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
vue-ui/src/main.js
Normal file
5
vue-ui/src/main.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { createApp } from 'vue';
|
||||||
|
import App from './App.vue';
|
||||||
|
import './assets/main.css';
|
||||||
|
|
||||||
|
createApp(App).mount('#app');
|
||||||
10
vue-ui/vite.config.js
Normal file
10
vue-ui/vite.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue()],
|
||||||
|
server: {
|
||||||
|
port: 5173,
|
||||||
|
open: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user