forked from GroupInCorner/ClassTest
Compare commits
41 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
24b1cefe0d | |
|
|
cf67d4d159 | |
|
|
4b22891b17 | |
|
|
93e51bc102 | |
|
|
0a86f4e673 | |
|
|
31d0de8b52 | |
|
|
34b32d9976 | |
|
|
c2ab344849 | |
|
|
05b5e932e8 | |
|
|
c5d4eab3e4 | |
|
|
af0cc07364 | |
|
|
317aea32db | |
|
|
6ec95ef8f3 | |
|
|
6a6662f3f3 | |
|
|
4d4edcd110 | |
|
|
617adaa112 | |
|
|
824d036135 | |
|
|
40ea9f981c | |
|
|
618557ce6e | |
|
|
96f2d39bbd | |
|
|
f5d8c0bf29 | |
|
|
f223594a7c | |
|
|
b6dc304600 | |
|
|
273479e857 | |
|
|
9bffe812b6 | |
|
|
8900abc0f8 | |
|
|
86c6d9d20e | |
|
|
6fe41eda14 | |
|
|
d88ff64a9f | |
|
|
10ec85f49a | |
|
|
6ffcc97900 | |
|
|
f6deb731aa | |
|
|
94e524d0d1 | |
|
|
1bd7dc849d | |
|
|
a305a26329 | |
|
|
be05dc805c | |
|
|
c167d7c5fc | |
|
|
ac23895aa3 | |
|
|
fbf832f88c | |
|
|
a93a3e73e7 | |
|
|
94bf28a30a |
|
|
@ -0,0 +1,61 @@
|
|||
# 持续集成:代码推送 / PR 时自动校验(Lint、类型检查、单测与覆盖率)
|
||||
name: CI Pipeline
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: ["main", "develop"]
|
||||
types: [opened, synchronize, reopened]
|
||||
push:
|
||||
branches: ["main", "develop"]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ gitlink.workflow }}-${{ gitlink.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
lint-and-type-check:
|
||||
name: Lint & Type Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
|
||||
- name: Type Check
|
||||
run: npm run type-check
|
||||
|
||||
test:
|
||||
name: Test Suite
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint-and-type-check
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
cache: "npm"
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: npm test -- --coverage
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
continue-on-error: true
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
# CI 说明(GitLink · Node)
|
||||
|
||||
## 这套 CI 起什么作用
|
||||
|
||||
在代码进入主分支之前,**自动跑一遍检查与测试**,主要目的:
|
||||
|
||||
- **尽早发现问题**:风格/规范错误、类型不一致、单测失败会在流水线里直接暴露,而不是等合并后才暴露。
|
||||
- **统一质量门槛**:团队约定好的 Lint、类型检查、测试命令由流水线强制执行,减少「本地能跑、别人拉下来不行」的情况。
|
||||
- **留下可追溯记录**:每次 Push / PR 对应一次流水线结果,便于回看是哪次提交引入了问题。
|
||||
- **覆盖率可见**:单测带 `--coverage` 并可选上传到 Codecov,便于观察测试是否覆盖关键逻辑。
|
||||
|
||||
本仓库的 CI 定义在 **`.GitLink/workflows/ci.yml`**。流水线里使用 **`gitlink`** 作为平台提供的上下文(写法上类似其他平台上的 `github`)。
|
||||
|
||||
---
|
||||
|
||||
## 什么时候会执行
|
||||
|
||||
| 事件 | 行为 |
|
||||
|------|------|
|
||||
| 向 `main` 或 `develop` **推送** | 跑完整 CI |
|
||||
| 针对 `main` / `develop` 的 **合并请求** | 跑完整 CI(含 PR 更新、重新打开等常见类型) |
|
||||
| **手动**触发 `workflow_dispatch` | 在流水线页面再跑一轮 |
|
||||
|
||||
同一分支上若短时间内多次触发,**`concurrency`** 会取消旧运行、只保留最新一次(`cancel-in-progress: true`),减少排队和资源占用。
|
||||
|
||||
---
|
||||
|
||||
## 流水线里做了什么
|
||||
|
||||
**Job 1:`lint-and-type-check`**
|
||||
|
||||
- 拉代码 → 使用 **Node 20**(并缓存 npm 依赖)→ **`npm ci`** 安装依赖
|
||||
- 执行 **`npm run lint`**:代码风格 / 静态规则
|
||||
- 执行 **`npm run type-check`**:类型相关检查(具体命令由你的脚本决定,例如 `tsc --noEmit`)
|
||||
|
||||
**Job 2:`test`(只有 Job 1 成功才会跑)**
|
||||
|
||||
- 再次安装依赖 → **`npm test -- --coverage`**:单元测试并生成覆盖率
|
||||
- 可选:把覆盖率上传到 **Codecov**(需配置 `CODECOV_TOKEN`;当前步骤为 **`continue-on-error: true`**,未配置时一般不会让整个流水线失败)
|
||||
|
||||
整体上:**先静态分析(Lint + 类型),再跑测试**,避免明显静态问题还继续跑完整测试浪费时间。
|
||||
|
||||
---
|
||||
|
||||
## 仓库里需要准备什么
|
||||
|
||||
根目录提供 **`package.json`**,且包含与 CI 中**同名**的脚本:
|
||||
|
||||
| 脚本 | 常见用途 |
|
||||
|------|----------|
|
||||
| `lint` | ESLint 等 |
|
||||
| `type-check` | TypeScript 检查等 |
|
||||
| `test` | Jest / Vitest 等,并支持附加 `--coverage` |
|
||||
|
||||
CI 使用 **`npm ci`**,建议提交 **`package-lock.json`**,保证依赖版本可复现。
|
||||
|
||||
---
|
||||
|
||||
## Secrets
|
||||
|
||||
| 名称 | 用途 |
|
||||
|------|------|
|
||||
| `CODECOV_TOKEN` | 上传覆盖率到 Codecov(可选;不需要可在工作流里删掉上传步骤) |
|
||||
|
||||
在 GitLink 仓库的 **设置 → Secrets**(名称以平台界面为准)中配置。
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
- **提示找不到脚本**:核对 `package.json` 里是否有 `lint`、`type-check`、`test`。
|
||||
- **`npm ci` 失败**:确认锁文件已提交,且本地用 Node 20 能同样安装成功。
|
||||
- **Codecov 报错**:配置 `CODECOV_TOKEN`,或删除「Upload coverage」步骤。
|
||||
|
||||
若改用 **pnpm / yarn**,需把工作流里的安装命令、缓存方式改成与包管理器一致。
|
||||
|
||||
---
|
||||
|
||||
## 同目录下其他流水线(简要)
|
||||
|
||||
| 文件 | 作用 |
|
||||
|------|------|
|
||||
| `deploy-staging.yml` | 预发布环境构建镜像与部署 |
|
||||
| `deploy-prod.yml` | 生产环境部署(通常配合人工确认) |
|
||||
| `security-scheduled.yml` | 定时或手动的安全扫描(如 Trivy) |
|
||||
|
||||
它们与 **CI** 相互独立:CI 负责「代码质量」,部署与安全扫描由对应文件负责。
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# 生产发布:手动确认后执行(审批由 Environment 保护规则承担)
|
||||
name: Deploy to Production
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
confirm:
|
||||
description: '确认发布生产环境时请填写 deploy'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to Production
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
if: gitlink.event.inputs.confirm == 'deploy'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Deploy to Production Server
|
||||
env:
|
||||
PROD_API_KEY: ${{ secrets.PROD_API_KEY }}
|
||||
run: echo "在此替换为真实生产部署脚本,密钥仅通过 Secrets 注入"
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
# 预发布:合并到 main 后构建镜像并部署到 Staging
|
||||
# 镜像仓库域名以 GitLink 平台「制品 / 容器镜像」文档为准;若与默认不一致,请修改下方 GITLINK_REGISTRY
|
||||
name: Deploy to Staging
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
GITLINK_REGISTRY: registry.gitlink.org.cn
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
name: Build and Push Docker Image
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to GitLink Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.GITLINK_REGISTRY }}
|
||||
username: ${{ gitlink.actor }}
|
||||
password: ${{ secrets.GITLINK_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: true
|
||||
tags: ${{ env.GITLINK_REGISTRY }}/${{ gitlink.repository }}:staging
|
||||
|
||||
deploy:
|
||||
name: Deploy to Staging Environment
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-and-push
|
||||
environment: staging
|
||||
steps:
|
||||
- name: Deploy to Staging Server
|
||||
run: echo "在此替换为真实部署:kubectl / SSH / 云厂商 Action 等"
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# 运维与安全:定时扫描(Trivy)
|
||||
name: Security Scan
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 2 * * *" # 每日 UTC 02:00
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
trivy-repo:
|
||||
name: Trivy filesystem scan
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
scan-type: "fs"
|
||||
scan-ref: "."
|
||||
severity: "CRITICAL,HIGH"
|
||||
continue-on-error: true
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
version: 2
|
||||
name: 每日定时检查流水线
|
||||
description: ""
|
||||
global:
|
||||
concurrent: 1
|
||||
cache: path
|
||||
trigger:
|
||||
type: cron
|
||||
schedule: 0 0 12 * * ?
|
||||
workflow:
|
||||
- ref: start
|
||||
name: 开始
|
||||
task: start
|
||||
|
||||
- ref: git_clone_0
|
||||
name: git clone
|
||||
task: git_clone@1.2.9
|
||||
input:
|
||||
remote_url: '"https://gitlink.org.cn/GroupInCorner/ClassTest.git"'
|
||||
ref: '"refs/heads/master"' # 如果你的主分支是 main,请改成 refs/heads/main
|
||||
commit_id: '""'
|
||||
depth: 1
|
||||
needs:
|
||||
- start
|
||||
|
||||
- ref: shell_0
|
||||
name: shell
|
||||
image: mcr.microsoft.com/playwright/python:v1.38.0-focal # 如果不用 Playwright 可换成 python:3.8 等
|
||||
env:
|
||||
PROJECT: git_clone_0.git_path
|
||||
script:
|
||||
- apt update
|
||||
- apt install -y openjdk-8-jdk-headless
|
||||
- apt install -y unzip
|
||||
# 如果你的项目里没有 lib/allure-2.22.0,下面三行请直接删除
|
||||
- cd $PROJECT/lib/allure-2.22.0/bin
|
||||
- chmod +x allure
|
||||
- ls -l
|
||||
- cd $PROJECT
|
||||
- pip install pipenv
|
||||
- pipenv install --python 3.8 --skip-lock
|
||||
- pipenv run playwright install # 如果不用 Playwright 可删除
|
||||
- pipenv run python run.py # 如果你的入口脚本不是 run.py,请改成实际名称
|
||||
needs:
|
||||
- git_clone_0
|
||||
|
||||
- ref: extract_txt_0
|
||||
name: 文本内容提取
|
||||
task: floraachy/extract_txt@2.0
|
||||
input:
|
||||
file: git_clone_0.git_path + "/outputs/report/test_result.txt"
|
||||
needs:
|
||||
- shell_0
|
||||
|
||||
- ref: new_gitlink_issue_0
|
||||
name: 新建GitLink疑修Issue
|
||||
task: floraachy/new_gitlink_issue@1.0.1
|
||||
input:
|
||||
host: '"https://gitlink.org.cn"'
|
||||
project_url: '"GroupInCorner/ClassTest"'
|
||||
username: ((gitlink.username))
|
||||
password: ((gitlink.password))
|
||||
issue_assign: '"[]"' # 如需指派可填用户ID,如 '"[12345]"'
|
||||
issue_title: '"UI自动化测试报告"'
|
||||
issue_content: '""'
|
||||
issue_attach: git_clone_0.git_path + "/outputs/report/autotest_report.zip"
|
||||
needs:
|
||||
- extract_txt_0
|
||||
|
||||
- ref: end
|
||||
name: 结束
|
||||
task: end
|
||||
needs:
|
||||
- new_gitlink_issue_0
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
version: 2
|
||||
name: 测试
|
||||
description: ""
|
||||
global:
|
||||
concurrent: 1
|
||||
workflow:
|
||||
- ref: start
|
||||
name: 开始
|
||||
task: start
|
||||
- ref: shell_0
|
||||
name: Python HelloWorld
|
||||
image: docker.jianmuhub.com/library/ubuntu:22.04
|
||||
script:
|
||||
- "#!/bin/bash"
|
||||
- set -e
|
||||
- ""
|
||||
- "# 更新软件源并安装Python3"
|
||||
- apt-get update && apt-get install -y python3 python3-pip
|
||||
- ""
|
||||
- "# 验证Python版本"
|
||||
- python3 --version
|
||||
- ""
|
||||
- "# 进入仓库根目录(流水线默认工作目录)"
|
||||
- cd /workspace
|
||||
- ""
|
||||
- "# 运行你的hello.py(根据文件位置选对应命令)"
|
||||
- "# 如果文件在 gitlink-test 文件夹里,用这行:"
|
||||
- python3 gitlink-test/hello.py
|
||||
- "# 如果文件在仓库根目录,改成:python3 hello.py"
|
||||
- ""
|
||||
- echo "✅ Python HelloWorld 运行成功!"
|
||||
needs:
|
||||
- start
|
||||
- ref: end
|
||||
name: 结束
|
||||
task: end
|
||||
needs:
|
||||
- shell_0
|
||||
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
name: 代码检查 CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main", "develop" ]
|
||||
pull_request:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: 拉取代码
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 查看当前文件
|
||||
run: ls -la
|
||||
|
||||
- name: 安装 C++ 编译器
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y g++
|
||||
|
||||
- name: 运行测试脚本
|
||||
run: bash test.sh
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
name: 构建与部署 CD
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: 拉取代码
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 安装 C++ 编译器
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y g++
|
||||
|
||||
- name: 构建项目
|
||||
run: |
|
||||
g++ hello.cpp -o hello
|
||||
echo "构建成功"
|
||||
|
||||
- name: 运行程序
|
||||
run: ./hello
|
||||
|
||||
- name: 模拟部署
|
||||
run: |
|
||||
echo "开始部署..."
|
||||
echo "当前只是课堂作业演示,没有真实服务器"
|
||||
echo "部署成功"
|
||||
31
1.cpp
31
1.cpp
|
|
@ -1,31 +0,0 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class GenshinImpact {
|
||||
public:
|
||||
string name;
|
||||
int element;
|
||||
|
||||
void showPower() {
|
||||
cout << "角色:" << name << endl;
|
||||
cout << "元素力爆发!原神牛逼!" << endl;
|
||||
cout << "风岩雷草水冰火,全图探索我做主!" << endl;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
GenshinImpact traveler;
|
||||
traveler.name = "旅行者";
|
||||
|
||||
cout << "========================================" << endl;
|
||||
cout << " 原神牛逼 " << endl;
|
||||
cout << "========================================" << endl;
|
||||
traveler.showPower();
|
||||
|
||||
cout << endl;
|
||||
cout << "提瓦特大陆最强!YYDS!" << endl;
|
||||
cout << "原神永远滴神!!!" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/gitlink-test.iml" filepath="$PROJECT_DIR$/.idea/gitlink-test.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="e5f42039-298a-45a4-af5e-391044745f62" name="更改" comment="" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ProjectColorInfo"><![CDATA[{
|
||||
"associatedIndex": 3
|
||||
}]]></component>
|
||||
<component name="ProjectId" id="3Cnrwg1yepNHJLUQdLhI0TwSUFu" />
|
||||
<component name="ProjectViewState">
|
||||
<option name="hideEmptyMiddlePackages" value="true" />
|
||||
<option name="showLibraryContents" value="true" />
|
||||
</component>
|
||||
<component name="PropertiesComponent"><![CDATA[{
|
||||
"keyToString": {
|
||||
"Python.hello.executor": "Run",
|
||||
"RunOnceActivity.ShowReadmeOnStart": "true",
|
||||
"nodejs_package_manager_path": "npm",
|
||||
"vue.rearranger.settings.migration": "true"
|
||||
}
|
||||
}]]></component>
|
||||
<component name="SharedIndexes">
|
||||
<attachedChunks>
|
||||
<set>
|
||||
<option value="bundled-js-predefined-d6986cc7102b-7c0b70fcd90d-JavaScript-PY-242.21829.153" />
|
||||
<option value="bundled-python-sdk-464836ebc622-b74155a9e76b-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-242.21829.153" />
|
||||
</set>
|
||||
</attachedChunks>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="应用程序级" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="默认任务">
|
||||
<changelist id="e5f42039-298a-45a4-af5e-391044745f62" name="更改" comment="" />
|
||||
<created>1777032414742</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1777032414742</updated>
|
||||
<workItem from="1777032416279" duration="8000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="3" />
|
||||
</component>
|
||||
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
||||
<SUITE FILE_PATH="coverage/gitlink_test$hello.coverage" NAME="hello 覆盖结果" MODIFIED="1777032420128" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
||||
</component>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# GitLink 测试代码
|
||||
print("Hello GitLink!")
|
||||
print("CI/CD 流水线测试成功 🎉")
|
||||
|
|
@ -0,0 +1,162 @@
|
|||
# ---> Python
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2026 BCZZB123
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# jiahao-run
|
||||
|
||||
|
|
@ -0,0 +1,274 @@
|
|||
import pygame
|
||||
import sys
|
||||
from pygame.locals import *
|
||||
import os
|
||||
import random
|
||||
from pygame.sprite import Sprite
|
||||
|
||||
bushu_have = []
|
||||
beibei = os.path.dirname(os.path.abspath(__file__))
|
||||
pygame.init()
|
||||
screen = pygame.display.set_mode((900, 700))
|
||||
pygame.display.set_caption('嘉豪快跑')
|
||||
gameover = False
|
||||
FPS = 50
|
||||
clock = pygame.time.Clock()
|
||||
BG_speed = 5
|
||||
Gbei_x, Gbei_y = 0, 0
|
||||
Xbei_x, Xbei_y = 900, 0
|
||||
player_x = 170
|
||||
player_y = 450
|
||||
is_jump = False
|
||||
jump_speed = 0
|
||||
JUMP_FORCE = -15
|
||||
GRAVITY = 1
|
||||
jiahao_index = 0
|
||||
direction = 1
|
||||
current_jiahao = None
|
||||
show = pygame.sprite.Group()
|
||||
show2 = pygame.sprite.Group()
|
||||
wuping_speed = 5
|
||||
font = pygame.font.SysFont("SIMHEI",32)
|
||||
bushu = 0
|
||||
is_paxia = False
|
||||
|
||||
def BG_beijing():
|
||||
path = os.path.join(beibei, "素材", "背景.jpg")
|
||||
return pygame.transform.scale(pygame.image.load(path), (900, 700))
|
||||
|
||||
def XG_beijing():
|
||||
path = os.path.join(beibei, "素材", "背景.jpg")
|
||||
return pygame.transform.scale(pygame.image.load(path), (900, 700))
|
||||
|
||||
def BG_juese():
|
||||
path = os.path.join(beibei, "素材", "前.jpg")
|
||||
return pygame.transform.scale(pygame.image.load(path), (40, 75))
|
||||
|
||||
def XG_juese():
|
||||
path = os.path.join(beibei, "素材", "中.jpg")
|
||||
return pygame.transform.scale(pygame.image.load(path), (40, 75))
|
||||
|
||||
def DG_juese():
|
||||
path = os.path.join(beibei, "素材", "跳跃.jpg")
|
||||
return pygame.transform.scale(pygame.image.load(path), (40, 75))
|
||||
|
||||
def shiba():
|
||||
path = os.path.join(beibei, "素材", "失败.png")
|
||||
return pygame.transform.scale(pygame.image.load(path),(600,500))
|
||||
|
||||
def pazhe():
|
||||
path = os.path.join(beibei, "素材", "趴下.jpg")
|
||||
return pygame.transform.scale(pygame.image.load(path),(40,30))
|
||||
|
||||
#ef haha():
|
||||
# path = os.path.join(beibei, "素材", "嘉豪.jpg")
|
||||
# return pygame.transform.scale(pygame.image.load(path),(40,30))
|
||||
#其他功能
|
||||
#ahaha = haha()
|
||||
paxia = pazhe()
|
||||
shibai = shiba()
|
||||
|
||||
def over():
|
||||
global shibai
|
||||
screen.blit(shibai,(100,100))
|
||||
|
||||
def bu_update():
|
||||
global bushu
|
||||
text = font.render(f"步数:{bushu}",True,(0,0,0))
|
||||
screen.blit(text,(100,100))
|
||||
bushu += 5
|
||||
|
||||
class wuping(Sprite):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
path = os.path.join(beibei, "素材", "床.jpg")
|
||||
self.image = pygame.transform.scale(pygame.image.load(path), (30, 50))
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 900
|
||||
self.rect.y = 470
|
||||
|
||||
def wupingupdate(self):
|
||||
screen.blit(self.image, self.rect)
|
||||
|
||||
def yidonn(self):
|
||||
self.rect.x -= wuping_speed
|
||||
|
||||
def shangchu(self):
|
||||
if self.rect.x <= -50:
|
||||
self.kill()
|
||||
|
||||
class wuping2(Sprite):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
path = os.path.join(beibei, "素材", "乌鸦.jpg")
|
||||
self.image = pygame.transform.scale(pygame.image.load(path), (60, 35))
|
||||
self.rect = self.image.get_rect()
|
||||
self.rect.x = 900
|
||||
self.rect.y = 440
|
||||
|
||||
def update(self):
|
||||
screen.blit(self.image, self.rect)
|
||||
|
||||
def yidonn2(self):
|
||||
self.rect.x -= wuping_speed
|
||||
|
||||
def shangdiao(self):
|
||||
if self.rect.x <= -50:
|
||||
self.kill()
|
||||
|
||||
DG_jiahao = DG_juese()
|
||||
XG_jiahao = XG_juese()
|
||||
XG_bei = XG_beijing()
|
||||
BG_bei = BG_beijing()
|
||||
BG_jiahao = BG_juese()
|
||||
|
||||
images = [BG_jiahao, XG_jiahao]
|
||||
current_jiahao = images[0]
|
||||
|
||||
def tiaoyui():
|
||||
global player_y, jump_speed, is_jump, current_jiahao, is_paxia
|
||||
if is_jump:
|
||||
current_jiahao = DG_jiahao
|
||||
is_paxia = False
|
||||
jump_speed += GRAVITY
|
||||
player_y += jump_speed
|
||||
if player_y >= 450:
|
||||
player_y = 450
|
||||
current_jiahao = images[jiahao_index]
|
||||
is_jump = False
|
||||
jump_speed = 0
|
||||
|
||||
def yidong():
|
||||
global Gbei_x, Xbei_x
|
||||
Gbei_x -= BG_speed
|
||||
Xbei_x -= BG_speed
|
||||
if Gbei_x <= -900:
|
||||
Gbei_x = 900
|
||||
if Xbei_x <= -900:
|
||||
Xbei_x = 900
|
||||
|
||||
def check():
|
||||
global gameover
|
||||
if is_paxia:
|
||||
jiahao_rect = pygame.Rect(player_x, player_y + 45, 40, 30)
|
||||
else:
|
||||
jiahao_rect = pygame.Rect(player_x, player_y, 40, 75)
|
||||
for wu in show:
|
||||
if jiahao_rect.colliderect(wu.rect):
|
||||
gameover = True
|
||||
return
|
||||
|
||||
for ha in show2:
|
||||
if jiahao_rect.colliderect(ha.rect):
|
||||
gameover = True
|
||||
return
|
||||
|
||||
def reset_game():
|
||||
global gameover, bushu, Gbei_x, Xbei_x, player_y, is_jump, jump_speed
|
||||
global jiahao_index, current_jiahao, is_paxia
|
||||
gameover = False
|
||||
bushu = 0
|
||||
Gbei_x, Gbei_y = 0, 0
|
||||
Xbei_x, Xbei_y = 900, 0
|
||||
player_y = 450
|
||||
is_jump = False
|
||||
jump_speed = 0
|
||||
jiahao_index = 0
|
||||
is_paxia = False
|
||||
current_jiahao = images[0]
|
||||
show.empty()
|
||||
show2.empty()
|
||||
|
||||
def zuoxia():
|
||||
global current_jiahao
|
||||
if is_jump:
|
||||
return
|
||||
if is_paxia:
|
||||
current_jiahao = paxia
|
||||
else:
|
||||
current_jiahao = images[jiahao_index]
|
||||
|
||||
while True:
|
||||
for event in pygame.event.get():
|
||||
if event.type == QUIT:
|
||||
pygame.quit()
|
||||
sys.exit()
|
||||
if event.type == KEYDOWN:
|
||||
if event.key == K_SPACE and gameover:
|
||||
reset_game()
|
||||
if event.key == K_2 and not is_jump:
|
||||
is_paxia = True
|
||||
if event.type == KEYUP:
|
||||
if event.key == K_2:
|
||||
is_paxia = False
|
||||
|
||||
if not gameover:
|
||||
keys = pygame.key.get_pressed()
|
||||
jiahao_index += direction
|
||||
if jiahao_index >= len(images):
|
||||
jiahao_index = 0
|
||||
elif jiahao_index < 0:
|
||||
jiahao_index = len(images) - 1
|
||||
|
||||
if keys[K_1] and not is_jump and not is_paxia:
|
||||
is_jump = True
|
||||
jump_speed = JUMP_FORCE
|
||||
|
||||
|
||||
all_obs = list(show) + list(show2)
|
||||
all_obs.sort(key=lambda o: o.rect.x)
|
||||
for i in range(1, len(all_obs)):
|
||||
prev = all_obs[i-1]
|
||||
curr = all_obs[i]
|
||||
if curr.rect.x - prev.rect.x < 140:
|
||||
curr.kill()
|
||||
|
||||
if random.random() < 0.007:
|
||||
b = wuping()
|
||||
show.add(b)
|
||||
|
||||
for wu in show:
|
||||
wu.yidonn()
|
||||
wu.wupingupdate()
|
||||
wu.shangchu()
|
||||
|
||||
if random.random() < 0.008:
|
||||
z = wuping2()
|
||||
show2.add(z)
|
||||
|
||||
for ha in show2:
|
||||
ha.yidonn2()
|
||||
ha.update()
|
||||
ha.shangdiao()
|
||||
|
||||
yidong()
|
||||
tiaoyui()
|
||||
zuoxia()
|
||||
check()
|
||||
bu_update()
|
||||
|
||||
screen.fill((0, 0, 0))
|
||||
screen.blit(BG_bei, (Gbei_x, Gbei_y))
|
||||
screen.blit(XG_bei, (Xbei_x, Xbei_y))
|
||||
if is_paxia:
|
||||
screen.blit(current_jiahao, (player_x, player_y + 45))
|
||||
else:
|
||||
screen.blit(current_jiahao, (player_x, player_y))
|
||||
show.draw(screen)
|
||||
show2.draw(screen)
|
||||
|
||||
elif gameover:
|
||||
bushu_have.append(bushu)
|
||||
screen.fill((255,255,255))
|
||||
over()
|
||||
if bushu_have:
|
||||
max_score = max(bushu_have)
|
||||
current_text = font.render(f"本次步数:{bushu}", True, (150, 0, 150))
|
||||
screen.blit(current_text, (50, 50))
|
||||
max_text = font.render(f"最高分:{max_score}", True, (0, 0, 255))
|
||||
screen.blit(max_text, (50, 100))
|
||||
restart_text = font.render("按空格键重新开始", True, (0, 0, 0))
|
||||
screen.blit(restart_text, (300, 600))
|
||||
|
||||
pygame.display.update()
|
||||
clock.tick(FPS)
|
||||
127
mergeSort.cpp
127
mergeSort.cpp
|
|
@ -1,127 +0,0 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//归并
|
||||
void merge(vector<int> &a, int left, int mid, int right){
|
||||
//临时数组用于存放排序后结果
|
||||
vector<int> res;
|
||||
|
||||
//两个指针用于标记
|
||||
int i = left;
|
||||
int j = mid + 1;
|
||||
|
||||
//比较
|
||||
while (i <= mid && j <= right)
|
||||
{
|
||||
if (a[i] < a[j])
|
||||
{
|
||||
res.push_back(a[i]);
|
||||
i++;
|
||||
} else if (a[i] == a[j])
|
||||
{
|
||||
res.push_back(a[i]);
|
||||
res.push_back(a[j]);
|
||||
i++;
|
||||
j++;
|
||||
}else if (a[i] > a[j])
|
||||
{
|
||||
res.push_back(a[j]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
//处理剩余
|
||||
while (i <= mid)
|
||||
{
|
||||
res.push_back(a[i]);
|
||||
i++;
|
||||
}
|
||||
while (j <= right)
|
||||
{
|
||||
res.push_back(a[j]);
|
||||
j++;
|
||||
}
|
||||
|
||||
//覆盖操作
|
||||
for (int t = 0; t < res.size(); t++)
|
||||
{
|
||||
a[left + t] = res[t];
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//归并排序
|
||||
void mergeSort(vector<int> &a, int left, int right){
|
||||
//区间内只有一个元素
|
||||
if(left == right) return;
|
||||
|
||||
//求中点,划分区间
|
||||
int mid = (left + right) / 2;
|
||||
//递归处理
|
||||
mergeSort(a, left, mid);
|
||||
mergeSort(a, mid + 1, right);
|
||||
|
||||
//归并
|
||||
merge(a, left, mid, right);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 打印数组
|
||||
void printVector(const vector<int>& a){
|
||||
for(int i = 0; i < a.size(); i++){
|
||||
cout << a[i] << " ";
|
||||
}
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
// 测试函数
|
||||
void test(){
|
||||
{
|
||||
vector<int> a = {5, 2, 4, 1, 3};
|
||||
mergeSort(a, 0, a.size() - 1);
|
||||
cout << "Test 1: ";
|
||||
printVector(a); // 期望: 1 2 3 4 5
|
||||
}
|
||||
|
||||
{
|
||||
vector<int> a = {8, 7, 6, 5, 4};
|
||||
mergeSort(a, 0, a.size() - 1);
|
||||
cout << "Test 2: ";
|
||||
printVector(a); // 期望: 4 5 6 7 8
|
||||
}
|
||||
|
||||
{
|
||||
vector<int> a = {1, 2, 3, 4, 5};
|
||||
mergeSort(a, 0, a.size() - 1);
|
||||
cout << "Test 3: ";
|
||||
printVector(a); // 期望: 1 2 3 4 5
|
||||
}
|
||||
|
||||
{
|
||||
vector<int> a = {3, 1, 2, 3, 1};
|
||||
mergeSort(a, 0, a.size() - 1);
|
||||
cout << "Test 4: ";
|
||||
printVector(a); // 期望: 1 1 2 3 3
|
||||
}
|
||||
|
||||
{
|
||||
vector<int> a = {10};
|
||||
mergeSort(a, 0, a.size() - 1);
|
||||
cout << "Test 5: ";
|
||||
printVector(a); // 期望: 10
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# 2026-04-17
|
||||
|
||||
## 奶龙跳跃游戏
|
||||
|
||||
- 完成 `d:/download/nailong/nailong_game.html` 的开发,仿 Chrome 离线恐龙游戏风格
|
||||
- 游戏角色使用工作区中的 `nai.png`(奶龙图片)
|
||||
- 功能特性:
|
||||
- Canvas 渲染,800×250 画布
|
||||
- 空格/↑/点击/触屏跳跃,支持二段跳(二段跳有旋转动画)
|
||||
- 障碍物含 3 种仙人掌 + 2 种飞鸟(高飞/低飞)
|
||||
- 速度随时间加快(5→14)
|
||||
- 落地压缩/起跳拉伸动画、粒子碰撞特效、百分里程碑金色闪光
|
||||
- 云朵视差背景、地面滚动纹理
|
||||
- 本地最高分记录(当局内)
|
||||
- 通过 http-server 本地 8765 端口预览
|
||||
|
||||
## 奶龙游戏更新(19:47)
|
||||
|
||||
- 所有字体/文字颜色改为黄色(#f5d020)
|
||||
- 计分规则改为跳过一个障碍物 +1 分,每个障碍物添加 passed 标记防重复计分
|
||||
- 跳过障碍物时显示黄色 "+1" 浮动弹出动画
|
||||
- 死亡后按空格/点击直接复活进入 playing,不再经过 waiting 中间状态
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 155 KiB |
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
echo "开始编译 hello.cpp..."
|
||||
|
||||
g++ hello.cpp -o hello
|
||||
|
||||
echo "开始运行程序..."
|
||||
|
||||
output=$(./hello)
|
||||
|
||||
echo "程序输出:$output"
|
||||
|
||||
if [ "$output" = "Hello, GitLink!" ]; then
|
||||
echo "测试通过"
|
||||
exit 0
|
||||
else
|
||||
echo "测试失败"
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#include<iostream>
|
||||
int main(){
|
||||
std::cout<<"hello world"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
name: CI 代码质量检查
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
check-code:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 拉取代码
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 配置 Python 环境
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: 安装 Python 依赖
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install flake8 pytest
|
||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||
|
||||
- name: Python 代码格式检查
|
||||
run: flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
|
||||
continue-on-error: false
|
||||
|
||||
- name: Python 单元测试
|
||||
run: pytest --verbose
|
||||
continue-on-error: false
|
||||
|
||||
- name: HTML 文件检查(可选,不报错)
|
||||
run: echo "HTML 静态文件检查完成"
|
||||
continue-on-error: true
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
name: CD 自动部署
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
tags: [ 'v*' ]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 拉取代码
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: 配置 Python 环境
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: 安装 Python 依赖
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||
|
||||
- name: 运行Python脚本(如果有需要)
|
||||
run: echo "Python 脚本执行完成(有需要再改这里)"
|
||||
continue-on-error: true
|
||||
|
||||
- name: 静态HTML文件部署
|
||||
run: echo "静态HTML文件部署完成(有服务器再改这里)"
|
||||
continue-on-error: true
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
name: 辅助维护任务
|
||||
|
||||
# 两种触发方式:定时自动 + 手动点击触发
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *' # 每天凌晨自动运行
|
||||
workflow_dispatch: # 允许手动点击运行
|
||||
|
||||
jobs:
|
||||
helper-task:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: 清理过期文件 + 安全扫描
|
||||
run: |
|
||||
echo "执行定时清理任务"
|
||||
echo "执行依赖安全漏洞扫描"
|
||||
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#include<iostream>
|
||||
int main(){
|
||||
std::cout<<"hello world"<<std::endl;
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue