ci: 基座切 idealjs/node:24.21.0-bookworm-slim(crane 直传转推,digest 一致);Dockerfile 移仓库根,按 依赖清单→安装→打包 分层,yarn4 直调 yarnPath 脚本免 corepack;CI 基座走 VPC 内网端点、凭据拆双 secret printf 登录、构建后登出清凭据、删产物上传步骤
This commit is contained in:
1 parent
99e8de3512
commit
4de4492354
4 files changed
+45
-49
No files matched your search
@@ -6,3 +6,11 @@
|
|||||||
**/playwright-report
|
**/playwright-report
|
||||||
apps/design-lab/e2e
|
apps/design-lab/e2e
|
||||||
.zcode*
|
.zcode*
|
||||||
|
.env
|
||||||
|
.pnp.*
|
||||||
|
.yarn/*
|
||||||
|
!.yarn/patches
|
||||||
|
!.yarn/plugins
|
||||||
|
!.yarn/releases
|
||||||
|
!.yarn/sdks
|
||||||
|
!.yarn/versions
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
name: Build Tutorial
|
name: Build Tutorial
|
||||||
|
|
||||||
# 主仓库 gitea.idealjs.com/idealjs/stack 的 CI:打包新教程站。
|
# 主仓库 gitea.idealjs.com/idealjs/stack 的 CI:打包新教程站。
|
||||||
# 构建环境全部封装在 apps/tutorial/Dockerfile(node24-alpine + yarn4 + npmmirror),
|
# 构建环境全部封装在仓库根 Dockerfile(node24-bookworm-slim + yarn4 + npmmirror),
|
||||||
# runner 用 buildah 无 daemon 执行——不依赖 runner 宿主的 node/docker,也不碰 github.com。
|
# runner 用 buildah 无 daemon 执行——不依赖 runner 宿主的 node/docker,也不碰 github.com。
|
||||||
# 源码:gitea API tarball(同机房)
|
# 源码:gitea API tarball(同机房);产物留在镜像 stack-tutorial:ci 内(/repo/apps/tutorial/dist)
|
||||||
# 产物:滚动 release「ci-dist」资产(node 取自镜像挂载层,原生 fetch 上传)
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
@@ -24,7 +23,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
wget -q "$API/archive/$GITHUB_SHA.tar.gz" -O /tmp/src.tgz
|
wget -q "$API/archive/$GITHUB_SHA.tar.gz" -O /tmp/src.tgz
|
||||||
tar -xzf /tmp/src.tgz --strip-components=1
|
tar -xzf /tmp/src.tgz --strip-components=1
|
||||||
ls apps/tutorial/Dockerfile
|
ls Dockerfile
|
||||||
|
|
||||||
- name: 装 buildah(runner 无 docker;buildah 无 daemon 即可构建)
|
- name: 装 buildah(runner 无 docker;buildah 无 daemon 即可构建)
|
||||||
run: |
|
run: |
|
||||||
@@ -35,41 +34,20 @@ jobs:
|
|||||||
|
|
||||||
- name: buildah 登录阿里云镜像仓(基座为私有 idealjs/node)
|
- name: buildah 登录阿里云镜像仓(基座为私有 idealjs/node)
|
||||||
env:
|
env:
|
||||||
ALIYUN_AUTH: ${{ secrets.ALIYUN_AUTH }}
|
ALIYUN_DOCKER_USERNAME: ${{ secrets.ALIYUN_DOCKER_USERNAME }}
|
||||||
|
ALIYUN_DOCKER_PASSWORD: ${{ secrets.ALIYUN_DOCKER_PASSWORD }}
|
||||||
run: |
|
run: |
|
||||||
echo "$ALIYUN_AUTH" | buildah login --username "${ALIYUN_AUTH%%:*}" --password-stdin registry.cn-hangzhou.aliyuncs.com
|
printf '%s' "$ALIYUN_DOCKER_PASSWORD" | buildah login --username "$ALIYUN_DOCKER_USERNAME" --password-stdin registry.cn-hangzhou.aliyuncs.com
|
||||||
|
# authfile 按域名区分——构建走 VPC 端点,需单独 login(凭据相同)
|
||||||
|
printf '%s' "$ALIYUN_DOCKER_PASSWORD" | buildah login --username "$ALIYUN_DOCKER_USERNAME" --password-stdin registry-vpc.cn-hangzhou.aliyuncs.com
|
||||||
|
|
||||||
- name: buildah 构建镜像(环境封装在 Dockerfile)
|
- name: buildah 构建镜像(环境封装在 Dockerfile)
|
||||||
run: |
|
run: |
|
||||||
buildah build --storage-driver=vfs -f apps/tutorial/Dockerfile -t stack-tutorial:ci .
|
# runner 与镜像仓同 region(杭州)——基座走 VPC 内网端点,快且不占公网带宽
|
||||||
|
buildah build --storage-driver=vfs --build-arg BASE_REGISTRY=registry-vpc.cn-hangzhou.aliyuncs.com -f Dockerfile -t stack-tutorial:ci .
|
||||||
|
|
||||||
- name: 取产物并上传 release(node 取自镜像挂载层)
|
- name: buildah 登出(清掉 runner 上 auth.json 里的凭据;长驻 runner 不留凭据)
|
||||||
env:
|
if: always()
|
||||||
TOK: ${{ secrets.CI_TOKEN || github.token }}
|
|
||||||
run: |
|
run: |
|
||||||
CID=$(buildah from localhost/stack-tutorial:ci)
|
buildah logout registry.cn-hangzhou.aliyuncs.com || true
|
||||||
MNT=$(buildah mount "$CID")
|
buildah logout registry-vpc.cn-hangzhou.aliyuncs.com || true
|
||||||
ls "$MNT/repo/apps/tutorial/dist/index.html"
|
|
||||||
tar -czf /tmp/tutorial-dist.tar.gz -C "$MNT/repo/apps/tutorial/dist" .
|
|
||||||
export LD_LIBRARY_PATH="$MNT/usr/lib"
|
|
||||||
cat > /tmp/upload.mjs <<'JS'
|
|
||||||
const API = process.env.API
|
|
||||||
const H = { Authorization: `token ${process.env.TOK}` }
|
|
||||||
const j = async (u, opt) => { const r = await fetch(API + u, { ...opt, headers: { ...H, ...(opt?.headers || {}) } }); return { ok: r.ok, status: r.status, data: r.status === 204 ? null : await r.json().catch(() => null) } }
|
|
||||||
let rid
|
|
||||||
let r = await j('/releases/tags/ci-dist')
|
|
||||||
if (r.ok) rid = r.data.id
|
|
||||||
else {
|
|
||||||
r = await j('/releases', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tag_name: 'ci-dist', name: 'CI 产物(滚动更新)', body: '每次构建的最新 dist。', draft: false, prerelease: true }) })
|
|
||||||
if (r.ok) rid = r.data.id
|
|
||||||
}
|
|
||||||
if (!rid) { console.log(`::warning::release 不可用(${r.status})——构建已成功,产物留在 runner`); process.exit(0) }
|
|
||||||
for (const a of (await j(`/releases/${rid}/assets`)).data || []) await j(`/releases/${rid}/assets/${a.id}`, { method: 'DELETE' })
|
|
||||||
const fd = new FormData()
|
|
||||||
fd.append('attachment', new Blob([await (await import('node:fs/promises')).readFile('/tmp/tutorial-dist.tar.gz')]), 'tutorial-dist.tar.gz')
|
|
||||||
const up = await fetch(`${API}/releases/${rid}/assets?name=tutorial-dist.tar.gz`, { method: 'POST', headers: H, body: fd })
|
|
||||||
console.log(up.ok ? `产物下载:${(await up.json()).browser_download_url}` : `上传失败 ${up.status}`)
|
|
||||||
JS
|
|
||||||
"$MNT/usr/local/bin/node" /tmp/upload.mjs
|
|
||||||
buildah unmount "$CID" >/dev/null 2>&1 || true
|
|
||||||
buildah rm "$CID" >/dev/null 2>&1 || true
|
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
# 教程站构建镜像——CI 用 buildah(无 daemon)执行,本地 docker/podman build 同样可用。
|
||||||
|
# 基座=自家阿里云镜像仓(idealjs/node,由官方 node:24.21.0-bookworm-slim 转推;私有仓,需 login)。
|
||||||
|
# 默认公网端点(本地可用);阿里云同 region 的 CI 传 --build-arg BASE_REGISTRY=registry-vpc.cn-hangzhou.aliyuncs.com 走内网。
|
||||||
|
ARG BASE_REGISTRY=registry.cn-hangzhou.aliyuncs.com
|
||||||
|
FROM ${BASE_REGISTRY}/idealjs/node:24.21.0-bookworm-slim
|
||||||
|
|
||||||
|
ENV YARN_NPM_REGISTRY_SERVER=https://registry.npmmirror.com
|
||||||
|
WORKDIR /workspace
|
||||||
|
|
||||||
|
# ① 依赖配置——只拷贝清单/锁文件/yarn 运行时,源码变更不失效依赖层
|
||||||
|
COPY .yarnrc.yml package.json yarn.lock ./
|
||||||
|
COPY .yarn/releases/yarn-4.9.2.cjs .yarn/releases/
|
||||||
|
COPY apps/tutorial/package.json apps/tutorial/
|
||||||
|
COPY apps/design-lab/package.json apps/design-lab/
|
||||||
|
COPY packages/design-system/package.json packages/design-system/
|
||||||
|
COPY packages/stack-idealjs/package.json packages/stack-idealjs/
|
||||||
|
|
||||||
|
# ② 安装依赖——yarn 4.9.2 由 yarnPath(.yarn/releases)提供,node 直调脚本,不依赖 corepack/全局 yarn
|
||||||
|
RUN node .yarn/releases/yarn-4.9.2.cjs install --immutable
|
||||||
|
|
||||||
|
# ③ 打包——monorepo 全量源码(.dockerignore 瘦身,无 node_modules/dist);产物在 /workspace/apps/tutorial/dist
|
||||||
|
COPY . .
|
||||||
|
RUN node .yarn/releases/yarn-4.9.2.cjs workspace @stack/tutorial build
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# 教程站构建镜像——CI 用 buildah(无 daemon)执行,本地 docker/podman build 同样可用。
|
|
||||||
# 基座=自家阿里云镜像仓(idealjs/node,由官方 node:24.14.0-alpine 转推;私有仓,CI 需 buildah login)。
|
|
||||||
FROM registry.cn-hangzhou.aliyuncs.com/idealjs/node:24.14.0-alpine
|
|
||||||
|
|
||||||
ENV YARN_NPM_REGISTRY_SERVER=https://registry.npmmirror.com
|
|
||||||
WORKDIR /repo
|
|
||||||
|
|
||||||
# monorepo 全量上下文(.dockerignore 瘦身);依赖与构建同层——lockfile 由 --immutable 锁定
|
|
||||||
COPY . .
|
|
||||||
RUN rm -f /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
||||||
&& corepack enable \
|
|
||||||
&& yarn install --immutable \
|
|
||||||
&& yarn workspace @stack/tutorial build
|
|
||||||
Reference in new issue
Block a user