ci(gitea): automate development delivery and manual releases
This commit is contained in:
1 parent
0d1e63b212
commit
0eb1b4696a
5 files changed
+283
-352
No files matched your search
+80
-117
@@ -4,7 +4,6 @@ on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -18,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 55
|
||||
env:
|
||||
CGO_ENABLED: '0'
|
||||
CI_RUN_ID: ${{ gitea.run_id }}
|
||||
steps:
|
||||
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
@@ -27,68 +26,12 @@ jobs:
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: false
|
||||
- name: Install frontend dependencies
|
||||
- name: Check CI behavior and project
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare [email protected] --activate
|
||||
pnpm -C web install --frozen-lockfile --registry=https://registry.npmjs.org
|
||||
- name: Check and build frontend
|
||||
run: |
|
||||
pnpm -C web lint:check
|
||||
pnpm -C web typecheck
|
||||
pnpm -C web test
|
||||
pnpm -C web build
|
||||
pnpm -C web build:demo
|
||||
- name: Check backend
|
||||
run: |
|
||||
go vet -tags dev ./...
|
||||
go test ./internal/...
|
||||
go test -tags dev ./web ./cmd/rawmark
|
||||
go vet ./...
|
||||
go test ./web ./cmd/rawmark
|
||||
- name: Test filesystem permissions as an unprivileged user
|
||||
run: |
|
||||
for package in vault watch; do
|
||||
go test -c -o "/tmp/rawmark-$package.test" "./internal/$package"
|
||||
(cd "internal/$package" && runuser -u node -- "/tmp/rawmark-$package.test" -test.v)
|
||||
done
|
||||
- name: Build platform packages and smoke-test Linux amd64
|
||||
run: |
|
||||
mkdir -p package/licenses downloads
|
||||
cp LICENSE package/
|
||||
cp web/LICENSE package/licenses/vue3-starter-MIT.txt
|
||||
cp web/src/common/appearance/fonts/*-OFL.txt package/licenses/
|
||||
cp web/src/common/appearance/fonts/maple/LICENSE.txt package/licenses/Maple-Mono-OFL.txt
|
||||
for target in linux/amd64 linux/arm64 windows/amd64 darwin/arm64 darwin/amd64; do
|
||||
export GOOS="${target%/*}" GOARCH="${target#*/}"
|
||||
extension=''
|
||||
if [ "$GOOS" = windows ]; then extension='.exe'; fi
|
||||
rm -f package/rawmark package/rawmark.exe
|
||||
go vet ./...
|
||||
go build -trimpath -ldflags="-s -w -X main.releaseVersion=$(cat VERSION)" -o "package/rawmark$extension" ./cmd/rawmark
|
||||
if [ "$target" = linux/amd64 ]; then
|
||||
python3 scripts/smoke-release.py package/rawmark
|
||||
fi
|
||||
python3 scripts/package-release.py "$GOOS" "$GOARCH"
|
||||
done
|
||||
- name: Check upload sizes and generate checksums
|
||||
run: |
|
||||
python3 - <<'PY'
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
archives = sorted(Path('downloads').glob('rawmark_*'))
|
||||
if len(archives) != 5:
|
||||
raise SystemExit(f'Expected five platform packages, found {len(archives)}')
|
||||
checksums = []
|
||||
for archive in archives:
|
||||
size = archive.stat().st_size
|
||||
print(f'{archive.name}: {size:,} bytes')
|
||||
if size >= 90_000_000:
|
||||
raise SystemExit(f'{archive.name} exceeds the 90 MB upload budget (Cloudflare limit: 100 MB)')
|
||||
checksums.append(f'{hashlib.file_digest(archive.open("rb"), "sha256").hexdigest()} {archive.name}\n')
|
||||
Path('downloads/SHA256SUMS').write_text(''.join(checksums))
|
||||
PY
|
||||
python3 -m unittest discover -s scripts/tests -v
|
||||
sh scripts/ci-check.sh development
|
||||
- name: Package and smoke-test Linux amd64
|
||||
run: sh scripts/ci-package.sh development
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: linux-amd64
|
||||
@@ -96,50 +39,34 @@ jobs:
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: linux-arm64
|
||||
path: downloads/*_linux_arm64.tar.gz
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: windows-amd64
|
||||
path: downloads/*_windows_amd64.zip
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: darwin-arm64
|
||||
path: downloads/*_darwin_arm64.tar.gz
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: darwin-amd64
|
||||
path: downloads/*_darwin_amd64.tar.gz
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: checksums
|
||||
path: downloads/SHA256SUMS
|
||||
path: |
|
||||
downloads/SHA256SUMS
|
||||
downloads/build.json
|
||||
if-no-files-found: error
|
||||
retention-days: 7
|
||||
|
||||
docker-smoke:
|
||||
image:
|
||||
needs: check-and-package
|
||||
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
|
||||
runs-on: docker
|
||||
timeout-minutes: 15
|
||||
timeout-minutes: 20
|
||||
env:
|
||||
CI_RUN_ID: ${{ gitea.run_id }}
|
||||
CI_RUN_ATTEMPT: ${{ gitea.run_attempt }}
|
||||
CI_RESOURCE_LABEL: io.rawmark.ci.run=dev-${{ gitea.run_id }}-${{ gitea.run_attempt }}
|
||||
TEMP_IMAGE: rawmark-ci:${{ gitea.sha }}-${{ gitea.run_id }}-${{ gitea.run_attempt }}
|
||||
DOCKER_CONFIG: /tmp/rawmark-docker-auth
|
||||
outputs:
|
||||
image: ${{ steps.publish.outputs.image }}
|
||||
version: ${{ steps.publish.outputs.version }}
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
steps:
|
||||
- name: Install CI action and smoke-test runtimes
|
||||
- name: Install CI runtimes
|
||||
run: apk add --no-cache nodejs python3
|
||||
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
@@ -152,27 +79,63 @@ jobs:
|
||||
with:
|
||||
name: checksums
|
||||
path: downloads
|
||||
- name: Verify the tested binary archive
|
||||
run: |
|
||||
python3 - <<'PY'
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
expected = {line.split()[1]: line.split()[0] for line in Path('downloads/SHA256SUMS').read_text().splitlines()}
|
||||
archive = Path(f'downloads/rawmark_{Path("VERSION").read_text().strip()}_linux_amd64.tar.gz')
|
||||
with archive.open('rb') as source:
|
||||
assert hashlib.file_digest(source, 'sha256').hexdigest() == expected[archive.name]
|
||||
PY
|
||||
mkdir -p image/linux/amd64 image/data
|
||||
tar -xzf "downloads/rawmark_$(cat VERSION)_linux_amd64.tar.gz" -C image/linux/amd64
|
||||
- name: Build and test the isolated container image
|
||||
env:
|
||||
COMMIT_SHA: ${{ gitea.sha }}
|
||||
RUN_ID: ${{ gitea.run_id }}
|
||||
RUN_ATTEMPT: ${{ gitea.run_attempt }}
|
||||
- name: Verify, build and smoke-test the exact binary
|
||||
run: |
|
||||
set -eu
|
||||
image="rawmark-ci:$COMMIT_SHA-$RUN_ID-$RUN_ATTEMPT"
|
||||
docker build --build-arg TARGETARCH=amd64 --tag "$image" -f deploy/Dockerfile.release image
|
||||
trap 'docker image rm "$image"' EXIT
|
||||
python3 scripts/smoke-docker.py "$image" --client-container "$(hostname)"
|
||||
python3 scripts/release.py prepare-image
|
||||
docker build --provenance=false --build-arg TARGETARCH=amd64 --tag "$TEMP_IMAGE" \
|
||||
--label "org.opencontainers.image.revision=${{ gitea.sha }}" \
|
||||
--label "org.opencontainers.image.version=$(cat VERSION)" \
|
||||
-f deploy/Dockerfile.release image
|
||||
python3 scripts/smoke-docker.py "$TEMP_IMAGE" --client-container "$(hostname)" \
|
||||
--resource-label "$CI_RESOURCE_LABEL"
|
||||
- name: Publish immutable development image
|
||||
id: publish
|
||||
env:
|
||||
GITEA_RELEASE_TOKEN: ${{ secrets.RAWMARK_GITEA_TOKEN }}
|
||||
run: |
|
||||
set -eu
|
||||
mkdir -m 700 "$DOCKER_CONFIG"
|
||||
python3 scripts/release.py promote-development "$TEMP_IMAGE"
|
||||
- name: Clean only this attempt's resources and credentials
|
||||
if: always()
|
||||
run: |
|
||||
python3 scripts/ci-cleanup.py "$CI_RESOURCE_LABEL" --client-container "$(hostname)" --image "$TEMP_IMAGE"
|
||||
rm -rf "$DOCKER_CONFIG"
|
||||
|
||||
deploy-development:
|
||||
needs: image
|
||||
if: gitea.event_name == 'push' && gitea.ref == 'refs/heads/main'
|
||||
runs-on: docker
|
||||
timeout-minutes: 15
|
||||
container:
|
||||
image: docker:29-cli
|
||||
volumes:
|
||||
- /docker/main/rawmark-dev:/docker/main/rawmark-dev
|
||||
env:
|
||||
GITEA_API_URL: ${{ gitea.server_url }}/api/v1
|
||||
GITEA_RELEASE_TOKEN: ${{ secrets.RAWMARK_GITEA_TOKEN }}
|
||||
DOCKER_CONFIG: /tmp/rawmark-docker-auth
|
||||
DEPLOY_IMAGE: ${{ needs.image.outputs.image }}
|
||||
DEPLOY_VERSION: ${{ needs.image.outputs.version }}
|
||||
DEPLOY_COMMIT: ${{ gitea.sha }}
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
steps:
|
||||
- name: Install deployment runtimes
|
||||
run: apk add --no-cache nodejs python3 docker-cli-compose
|
||||
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Deploy only the independent development instance
|
||||
run: |
|
||||
set -eu
|
||||
mkdir -m 700 "$DOCKER_CONFIG"
|
||||
printf '%s' "$GITEA_RELEASE_TOKEN" | docker login git.134333.xyz --username eezd --password-stdin
|
||||
python3 scripts/deploy.py development --directory /docker/main/rawmark-dev \
|
||||
--image "$DEPLOY_IMAGE" --commit "$DEPLOY_COMMIT" --version "$DEPLOY_VERSION" \
|
||||
--client-container "$(hostname)"
|
||||
- name: Remove job credentials
|
||||
if: always()
|
||||
run: rm -rf "$DOCKER_CONFIG"
|
||||
@@ -0,0 +1,49 @@
|
||||
name: Deploy production manually
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Completed formal release version (X.Y.Z)
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: rawmark-production
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
if: gitea.ref == 'refs/heads/main'
|
||||
runs-on: docker
|
||||
timeout-minutes: 20
|
||||
container:
|
||||
image: docker:29-cli
|
||||
volumes:
|
||||
- /docker/main/rawmark:/docker/main/rawmark
|
||||
env:
|
||||
GITEA_API_URL: ${{ gitea.server_url }}/api/v1
|
||||
GITEA_READ_TOKEN: ${{ gitea.token }}
|
||||
RELEASE_VERSION: ${{ inputs.version }}
|
||||
DOCKER_CONFIG: /tmp/rawmark-anonymous-docker
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
steps:
|
||||
- name: Install deployment runtimes
|
||||
run: apk add --no-cache nodejs python3 docker-cli-compose
|
||||
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Verify completed release, back up and deploy only RawMark
|
||||
run: |
|
||||
set -eu
|
||||
mkdir -m 700 "$DOCKER_CONFIG"
|
||||
python3 scripts/deploy.py production --directory /docker/main/rawmark \
|
||||
--version "$RELEASE_VERSION" --client-container "$(hostname)"
|
||||
- name: Remove job configuration
|
||||
if: always()
|
||||
run: rm -rf "$DOCKER_CONFIG"
|
||||
@@ -0,0 +1,151 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: Version matching VERSION (X.Y.Z)
|
||||
required: true
|
||||
type: string
|
||||
commit:
|
||||
description: Full main commit SHA with successful development CI
|
||||
required: true
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: rawmark-release
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
GITEA_API_URL: ${{ gitea.server_url }}/api/v1
|
||||
CI_RUN_ID: ${{ gitea.run_id }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: gitea.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 55
|
||||
env:
|
||||
GITEA_RELEASE_TOKEN: ${{ secrets.RAWMARK_GITEA_TOKEN }}
|
||||
GITHUB_RELEASE_TOKEN: ${{ secrets.RAWMARK_GITHUB_TOKEN }}
|
||||
RELEASE_VERSION: ${{ inputs.version }}
|
||||
RELEASE_COMMIT: ${{ inputs.commit }}
|
||||
outputs:
|
||||
completed: ${{ steps.preflight.outputs.completed }}
|
||||
steps:
|
||||
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
ref: ${{ inputs.commit }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- name: Validate source, permissions and existing release checkpoint
|
||||
id: preflight
|
||||
run: python3 scripts/release.py preflight "$RELEASE_VERSION" "$RELEASE_COMMIT"
|
||||
- uses: https://github.com/actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: false
|
||||
- name: Check and build the five platform packages
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
run: |
|
||||
python3 -m unittest discover -s scripts/tests -v
|
||||
sh scripts/ci-check.sh release
|
||||
sh scripts/ci-package.sh release
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
with:
|
||||
name: linux-amd64
|
||||
path: downloads/*_linux_amd64.tar.gz
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
with:
|
||||
name: linux-arm64
|
||||
path: downloads/*_linux_arm64.tar.gz
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
with:
|
||||
name: windows-amd64
|
||||
path: downloads/*_windows_amd64.zip
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
with:
|
||||
name: darwin-amd64
|
||||
path: downloads/*_darwin_amd64.tar.gz
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
with:
|
||||
name: darwin-arm64
|
||||
path: downloads/*_darwin_arm64.tar.gz
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
with:
|
||||
name: checksums
|
||||
path: |
|
||||
downloads/SHA256SUMS
|
||||
downloads/build.json
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
- uses: https://github.com/actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
with:
|
||||
name: demo
|
||||
path: downloads/demo.zip
|
||||
compression-level: 0
|
||||
if-no-files-found: error
|
||||
retention-days: 30
|
||||
- name: Save immutable build checkpoint after artifact uploads
|
||||
if: steps.preflight.outputs.reuse == 'false'
|
||||
run: python3 scripts/release.py checkpoint
|
||||
|
||||
publish:
|
||||
needs: build
|
||||
if: needs.build.outputs.completed == 'false'
|
||||
runs-on: docker
|
||||
timeout-minutes: 55
|
||||
container:
|
||||
image: docker:29-cli
|
||||
env:
|
||||
GITEA_RELEASE_TOKEN: ${{ secrets.RAWMARK_GITEA_TOKEN }}
|
||||
GITHUB_RELEASE_TOKEN: ${{ secrets.RAWMARK_GITHUB_TOKEN }}
|
||||
CI_RESOURCE_LABEL: io.rawmark.ci.run=release-${{ gitea.run_id }}-${{ gitea.run_attempt }}
|
||||
DOCKER_CONFIG: /tmp/rawmark-docker-auth
|
||||
defaults:
|
||||
run:
|
||||
shell: sh
|
||||
steps:
|
||||
- name: Install publication runtimes
|
||||
run: apk add --no-cache nodejs python3 git skopeo
|
||||
- uses: https://github.com/actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
||||
with:
|
||||
ref: ${{ inputs.commit }}
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- name: Publish the original checked artifacts to both services
|
||||
run: |
|
||||
set -eu
|
||||
mkdir -m 700 "$DOCKER_CONFIG"
|
||||
python3 scripts/release.py publish
|
||||
- name: Clean only this attempt's test resources and credentials
|
||||
if: always()
|
||||
run: |
|
||||
python3 scripts/ci-cleanup.py "$CI_RESOURCE_LABEL" --client-container "$(hostname)"
|
||||
rm -rf "$DOCKER_CONFIG"
|
||||
@@ -12,7 +12,7 @@ Native downloads now cover five platforms:
|
||||
|
||||
- Platform-specific disk space queries, temporary storage and restore-record publication support Windows backup/restore.
|
||||
- Windows paths reject device names, alternate data streams and filename aliases at note/import/backup boundaries.
|
||||
- One release workflow tests each program on a native runner before packaging. Docker remains Linux amd64/arm64 and uses those tested programs.
|
||||
- One Gitea release workflow checks the project and cross-builds all five targets. Linux amd64 runs native lifecycle tests; Windows, macOS and Linux arm64 remain unverified at runtime. Docker remains Linux amd64/arm64 and uses the same packaged programs.
|
||||
- Archives contain the CLI web server and licenses; no desktop GUI, installer or code signing is included. macOS may require manual approval for the unsigned download.
|
||||
|
||||
### Try or install
|
||||
@@ -22,8 +22,8 @@ Native downloads now cover five platforms:
|
||||
- Verify downloads using `SHA256SUMS`, then follow the [deployment guide](https://github.com/eezd/RawMark/blob/v0.1.1/docs/deployment.md).
|
||||
- [English README](https://github.com/eezd/RawMark/blob/v0.1.1/README.md) · [中文说明](https://github.com/eezd/RawMark/blob/v0.1.1/README.zh-CN.md).
|
||||
|
||||
Preserve your complete data directory and mount configuration when upgrading, and back up first. No database migration or cleanup SQL is required. Existing v0.1.0 downloads remain available.
|
||||
Preserve your complete data directory and mount configuration when upgrading, and back up first. No historical cleanup SQL is required. This file is a release draft; availability depends on a completed formal release.
|
||||
|
||||
---
|
||||
|
||||
新增 Windows amd64、macOS Apple Silicon 和 Intel 原生程序,保留 Linux 双架构程序与 Docker 镜像。五个平台均在各自原生 runner 测试后打包,由同一个发布工作流完成。原生程序是网页服务端,不含桌面窗口、安装器或签名;macOS 首次运行可能需要手动允许。请先核对 SHA256SUMS,再参考部署指南。升级前备份并保留完整数据目录;无需执行数据库迁移或历史清理,v0.1.0 附件保持不变。
|
||||
新增 Windows amd64、macOS Apple Silicon 和 Intel 原生程序,保留 Linux 双架构程序与 Docker 镜像。同一个 Gitea 发布工作流完成检查与交叉构建;Linux amd64 执行原生生命周期测试,Windows、macOS 和 Linux arm64 尚未完成原生运行验收。原生程序是网页服务端,不含桌面窗口、安装器或签名;macOS 首次运行可能需要手动允许。请先核对 SHA256SUMS,再参考部署指南。升级前备份并保留完整数据目录,不重跑历史清理 SQL。此文件为发布草稿,产物是否可用以完整正式发布为准。
|
||||
@@ -1,232 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['v*']
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: rawmark-release
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- name: Validate release tag
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
version="$(cat VERSION)"
|
||||
[[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]
|
||||
test "$RELEASE_TAG" = "v$version"
|
||||
- uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
|
||||
with:
|
||||
node-version: '24'
|
||||
- name: Install frontend dependencies
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare [email protected] --activate
|
||||
pnpm -C web install --frozen-lockfile --registry=https://registry.npmjs.org
|
||||
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
- name: Check and build
|
||||
run: |
|
||||
pnpm -C web lint:check
|
||||
pnpm -C web typecheck
|
||||
pnpm -C web test
|
||||
pnpm -C web build
|
||||
pnpm -C web build:demo
|
||||
go vet -tags dev ./...
|
||||
go test ./internal/...
|
||||
go test -tags dev ./web ./cmd/rawmark
|
||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: frontend
|
||||
path: web/dist
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0
|
||||
with:
|
||||
path: web/dist-demo
|
||||
|
||||
native:
|
||||
needs: check
|
||||
strategy:
|
||||
fail-fast: false
|
||||
max-parallel: 2
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
arch: amd64
|
||||
runner: ubuntu-24.04
|
||||
extension: ''
|
||||
- os: linux
|
||||
arch: arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
extension: ''
|
||||
- os: windows
|
||||
arch: amd64
|
||||
runner: windows-2025
|
||||
extension: '.exe'
|
||||
- os: darwin
|
||||
arch: arm64
|
||||
runner: macos-15
|
||||
extension: ''
|
||||
- os: darwin
|
||||
arch: amd64
|
||||
runner: macos-15-intel
|
||||
extension: ''
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 30
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
env:
|
||||
CGO_ENABLED: '0'
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
with:
|
||||
name: frontend
|
||||
path: web/dist
|
||||
- name: Build and smoke-test native binary
|
||||
env:
|
||||
EXE: ${{ matrix.extension }}
|
||||
run: |
|
||||
mkdir -p package/licenses
|
||||
go build -trimpath -ldflags="-s -w -X main.releaseVersion=$(cat VERSION)" -o "package/rawmark$EXE" ./cmd/rawmark
|
||||
go vet ./...
|
||||
go test ./internal/... ./cmd/rawmark ./web
|
||||
python scripts/smoke-release.py "package/rawmark$EXE"
|
||||
- name: Package download
|
||||
env:
|
||||
ARCH: ${{ matrix.arch }}
|
||||
TARGET_OS: ${{ matrix.os }}
|
||||
run: |
|
||||
cp LICENSE package/
|
||||
cp web/LICENSE package/licenses/vue3-starter-MIT.txt
|
||||
cp web/src/common/appearance/fonts/*-OFL.txt package/licenses/
|
||||
cp web/src/common/appearance/fonts/maple/LICENSE.txt package/licenses/Maple-Mono-OFL.txt
|
||||
mkdir downloads
|
||||
python scripts/package-release.py "$TARGET_OS" "$ARCH"
|
||||
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
||||
with:
|
||||
name: native-${{ matrix.os }}-${{ matrix.arch }}
|
||||
path: downloads/*
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
|
||||
image:
|
||||
needs: native
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 20
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
outputs:
|
||||
digest: ${{ steps.build.outputs.digest }}
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
with:
|
||||
pattern: native-linux-*
|
||||
path: downloads
|
||||
merge-multiple: true
|
||||
- name: Prepare tested binaries
|
||||
run: |
|
||||
mkdir -p image/linux/amd64 image/linux/arm64 image/data
|
||||
for arch in amd64 arm64; do
|
||||
tar -xzf "downloads/rawmark_$(cat VERSION)_linux_$arch.tar.gz" -C "image/linux/$arch"
|
||||
done
|
||||
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
|
||||
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Publish version image
|
||||
id: build
|
||||
uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
|
||||
with:
|
||||
context: image
|
||||
file: deploy/Dockerfile.release
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ghcr.io/eezd/rawmark:${{ github.ref_name }}
|
||||
labels: |
|
||||
org.opencontainers.image.source=https://github.com/eezd/RawMark
|
||||
org.opencontainers.image.version=${{ github.ref_name }}
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.licenses=MIT
|
||||
- name: Smoke-test packaged image
|
||||
env:
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
run: |
|
||||
image="ghcr.io/eezd/rawmark:$RELEASE_TAG"
|
||||
test "$(docker run --rm "$image" --version)" = "RawMark $(cat VERSION)"
|
||||
trap 'docker rm -f rawmark-smoke; docker volume rm rawmark-smoke-data' EXIT
|
||||
docker run -d --name rawmark-smoke -v rawmark-smoke-data:/data -p 127.0.0.1:21876:8080 "$image"
|
||||
for attempt in {1..60}; do
|
||||
status="$(docker inspect --format '{{.State.Health.Status}}' rawmark-smoke)"
|
||||
if [ "$status" = healthy ]; then break; fi
|
||||
if [ "$status" = unhealthy ]; then docker logs rawmark-smoke; exit 1; fi
|
||||
sleep 1
|
||||
done
|
||||
test "$status" = healthy
|
||||
test "$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:21876/api/v1/tree)" = 401
|
||||
docker exec rawmark-smoke /rawmark healthcheck
|
||||
|
||||
pages:
|
||||
needs: image
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0
|
||||
- uses: actions/deploy-pages@368f82528645a54fb793d4d04e342629a3f51346 # v5.0.1
|
||||
id: deployment
|
||||
|
||||
release:
|
||||
needs: [image, pages]
|
||||
runs-on: ubuntu-24.04
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
||||
with:
|
||||
pattern: native-*
|
||||
path: downloads
|
||||
merge-multiple: true
|
||||
- uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
|
||||
- uses: docker/login-action@81c6f93d4bc991e510b342a00b419b3bb4efc5c6 # v4.7.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Publish release and stable image tags
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
RELEASE_TAG: ${{ github.ref_name }}
|
||||
IMAGE_DIGEST: ${{ needs.image.outputs.digest }}
|
||||
run: |
|
||||
(cd downloads && sha256sum *.tar.gz *.zip > SHA256SUMS)
|
||||
gh release create "$RELEASE_TAG" downloads/* --verify-tag --title "RawMark $RELEASE_TAG" --notes-file .github/release-notes.md --latest
|
||||
docker buildx imagetools create --tag "ghcr.io/eezd/rawmark:$(cat VERSION)" --tag ghcr.io/eezd/rawmark:latest "ghcr.io/eezd/rawmark@$IMAGE_DIGEST"
|
||||
Reference in new issue
Block a user