From e95f553174188ef180fe3ad2acf5aeedd963e6d0 Mon Sep 17 00:00:00 2001 From: biss Date: Tue, 21 Jul 2026 11:40:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0npm=E5=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitea/workflows/docker-publish.yml | 31 ++++++++++++++++++++++++++-- README.md | 13 +++++++----- compose.yaml | 2 +- package-lock.json | 32 ++++++++++++++--------------- 4 files changed, 54 insertions(+), 24 deletions(-) diff --git a/.gitea/workflows/docker-publish.yml b/.gitea/workflows/docker-publish.yml index 30cdd2c..7901863 100644 --- a/.gitea/workflows/docker-publish.yml +++ b/.gitea/workflows/docker-publish.yml @@ -1,4 +1,4 @@ -name: Build and publish Docker image +name: Build and publish Docker images on: push: @@ -10,6 +10,9 @@ jobs: publish: name: Test, build and publish runs-on: ubuntu-latest + permissions: + contents: read + releases: write steps: - name: Check out repository @@ -39,11 +42,20 @@ jobs: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Log in to Gitea Container Registry + uses: https://github.com/docker/login-action@v3 + with: + registry: git.biss.click + username: ${{ vars.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_TOKEN }} + - name: Generate image tags and labels id: metadata uses: https://github.com/docker/metadata-action@v5 with: - images: docker.io/${{ vars.DOCKERHUB_IMAGE }} + images: | + docker.io/${{ vars.DOCKERHUB_IMAGE }} + git.biss.click/biss/exam-information-system flavor: latest=false tags: | type=raw,value=latest,enable=${{ gitea.ref == 'refs/heads/master' }} @@ -62,3 +74,18 @@ jobs: labels: ${{ steps.metadata.outputs.labels }} cache-from: type=registry,ref=docker.io/${{ vars.DOCKERHUB_IMAGE }}:buildcache cache-to: type=registry,ref=docker.io/${{ vars.DOCKERHUB_IMAGE }}:buildcache,mode=max + + - name: Create Gitea release + if: gitea.ref_type == 'tag' + uses: https://gitea.com/actions/gitea-release-action@v1 + with: + token: ${{ secrets.GITEA_TOKEN }} + tag_name: ${{ gitea.ref_name }} + name: ${{ gitea.ref_name }} + body: | + Docker 镜像已发布: + + ```text + docker pull docker.io/${{ vars.DOCKERHUB_IMAGE }}:${{ steps.metadata.outputs.version }} + docker pull git.biss.click/biss/exam-information-system:${{ steps.metadata.outputs.version }} + ``` diff --git a/README.md b/README.md index 89cac56..7dd19d2 100644 --- a/README.md +++ b/README.md @@ -127,25 +127,28 @@ docker build --tag hengzhun-exam-system:local . 镜像默认监听 `0.0.0.0:4173`,以非 root 用户运行,并通过 `/api/public/home` 执行健康检查。需要连接 MySQL 或 Redis 时,用运行环境变量覆盖 `DATABASE_CLIENT`、`DATABASE_URL`/`MYSQL_*`、`REDIS_URL`;此时 SQLite 数据卷可以移除。 -#### Gitea Actions 自动发布到 Docker Hub +#### Gitea Actions 自动发布到 Docker Hub 与 Gitea 软件包 -工作流位于 `.gitea/workflows/docker-publish.yml`。它会先安装依赖并运行测试,然后构建 `linux/amd64`、`linux/arm64` 双架构镜像并推送到 Docker Hub。 +工作流位于 `.gitea/workflows/docker-publish.yml`。它会先安装依赖并运行测试,然后构建 `linux/amd64`、`linux/arm64` 双架构镜像,并同时推送到 Docker Hub 与 `git.biss.click/biss/exam-information-system`。 使用前需要完成以下配置: 1. 在 Docker Hub 创建目标仓库,并创建具有该仓库 Read & Write 权限的访问令牌。 2. 在 Gitea 仓库的 Actions Variables 中添加 `DOCKERHUB_IMAGE`,值为不带 registry 和 tag 的完整镜像名,例如 `yourname/exam-information-system`。 3. 在 Gitea 仓库的 Actions Secrets 中添加 `DOCKERHUB_USERNAME` 和 `DOCKERHUB_TOKEN`。前者填写 Docker Hub 用户名,后者填写访问令牌,不要填写账户密码。 -4. 确保 Gitea Actions 已启用,并且 `ubuntu-latest` Runner 能访问 Docker daemon、GitHub 和 Docker Hub。双架构构建还需要 Runner 允许 QEMU 注册步骤运行。 +4. 使用对 `biss` 组织拥有软件包写权限的 Gitea 账号,在“设置 → 应用 → 生成新令牌”中创建具有 Package Read & Write 权限的个人访问令牌。在仓库 Actions Variables 中添加 `REGISTRY_USERNAME`,值为该令牌所属的用户名;在 Actions Secrets 中添加 `REGISTRY_TOKEN`,值为个人访问令牌。自定义 Secret 不能使用 Gitea 保留的 `GITEA_` 前缀,也不能用工作流内置的 `GITEA_TOKEN` 代替该软件包令牌。 +5. 确保 Gitea Actions 与仓库的软件包注册表已启用,并且 `ubuntu-latest` Runner 能访问 Docker daemon、GitHub、Docker Hub 和 `git.biss.click`。双架构构建还需要 Runner 允许 QEMU 注册步骤运行。 -推送到 `master` 后会发布 `latest` 和 `sha-<短提交号>`;推送形如 `v1.2.3` 的 Git 标签后会发布 `1.2.3`、`1.2` 和对应的提交标签。例如: +推送到 `master` 后会发布 `latest` 和 `sha-<短提交号>`;推送形如 `v1.2.3` 的 Git 标签后会发布 `1.2.3`、`1.2` 和对应的提交标签,并在镜像推送成功后自动创建同名 Gitea Release。例如: ```powershell git tag v1.2.3 git push origin v1.2.3 ``` -工作流也支持从 Gitea Actions 页面手动运行。构建缓存保存为同一 Docker Hub 仓库中的 `buildcache` 标签,以加快后续构建。 +工作流也支持从 Gitea Actions 页面手动运行。构建缓存保存为同一 Docker Hub 仓库中的 `buildcache` 标签,以加快后续构建。Release 使用工作流内置的 `GITEA_TOKEN` 创建,无需添加额外 Secret;仓库或组织“Actions → General”中的任务令牌最大权限必须允许 Releases Write。 + +首次成功推送后,容器镜像会出现在 `biss` 所有者的软件包列表。Gitea 的软件包归属于用户或组织,不会天然归属于某个仓库;打开该软件包的设置页面,将它关联到 `Exam-Information-System`,即可让它显示在此仓库的“软件包”页。之后可使用 `docker pull git.biss.click/biss/exam-information-system:latest` 拉取。 需要清空并重建空业务库时运行 `npm run reset-db`。需要测试数据时再手动运行 `npm run seed-test-data`;导入脚本会读取项目根目录的 `.env`,并根据 `DATABASE_CLIENT` 选择 SQLite 或 MySQL。它会生成 4 所学校、360 名批量考生及 360 条不同状态的报名数据,并明确不生成考场编排计划和准考证。省市区县下拉数据位于 `src/data/china-regions.mjs`,当前版本为国家地名信息库截至 2025-12-31 的三级快照,并补入和康县(653228)与和安县(653229);从新版 CSV 更新时可运行 `node scripts/build-regions.mjs src/data/china-regions.mjs`。 diff --git a/compose.yaml b/compose.yaml index 2aab980..75d10ad 100644 --- a/compose.yaml +++ b/compose.yaml @@ -2,7 +2,7 @@ services: app: build: context: . - image: hengzhun-exam-system:local + image: exam-information-system:local init: true restart: unless-stopped env_file: diff --git a/package-lock.json b/package-lock.json index 3250482..8b4fdef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1787,12 +1787,12 @@ ] }, "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -2543,18 +2543,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/mdast-util-from-markdown": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", @@ -3843,6 +3831,18 @@ "node": ">=22.12.0" } }, + "node_modules/sanitize-html/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/saxes": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",