Files
IPTables-Management/.gitea/workflows/release.yml
ahdoawhfo 0068e787fb Set GIT_DEFAULT_HASH for SHA-256 repo
The repository is initialized with the SHA-256 object format, but
actions/checkout runs `git init` in the workspace before fetching.
Without GIT_DEFAULT_HASH=sha256 that init defaults to SHA-1 and fetch
fails with `mismatched algorithms: client sha1; server sha256`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 13:35:10 +08:00

235 lines
8.1 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: Build and Release
on:
workflow_dispatch:
inputs:
version:
description: '版本号 (留空则自动生成 v<YYYY.MM.DD>-<short-sha>)'
required: false
default: ''
prerelease:
description: '标记为预发布 (Pre-release)'
required: false
default: 'false'
type: choice
options:
- 'false'
- 'true'
draft:
description: '以草稿方式创建 Release (不对外公开)'
required: false
default: 'false'
type: choice
options:
- 'false'
- 'true'
skip_tests:
description: '跳过单元测试 (紧急构建时使用)'
required: false
default: 'false'
type: choice
options:
- 'false'
- 'true'
jobs:
build-release:
runs-on: ubuntu-latest
env:
# 仓库使用 SHA-256 对象格式actions/checkout 内部 `git init` 需在此模式下运行,否则 fetch 会报
# `mismatched algorithms: client sha1; server sha256`。
GIT_DEFAULT_HASH: sha256
steps:
- name: Checkout (full history)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install toolchain
run: |
set -euo pipefail
if [[ $EUID -ne 0 ]] && command -v sudo >/dev/null 2>&1; then
SUDO=sudo
else
SUDO=
fi
$SUDO apt-get update -qq
DEBIAN_FRONTEND=noninteractive $SUDO apt-get install -y -qq \
shellcheck jq curl tar coreutils ca-certificates
- name: Run shellcheck
run: |
set -euo pipefail
shellcheck iptables-forward.sh install.sh lib/*.sh tests/run_all.sh
- name: Run unit tests
if: ${{ inputs.skip_tests != 'true' }}
run: |
set -euo pipefail
bash tests/run_all.sh --skip-integration
- name: Compute version metadata
id: ver
run: |
set -euo pipefail
SHORT_SHA=$(git rev-parse --short=7 HEAD)
FULL_SHA=$(git rev-parse HEAD)
DATE=$(date -u +%Y.%m.%d)
BUILD_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
if [[ -n "${{ inputs.version }}" ]]; then
VERSION="${{ inputs.version }}"
else
VERSION="v${DATE}-${SHORT_SHA}"
fi
TAG="${VERSION}"
TITLE="IPTables 端口转发管理工具 ${VERSION}"
ARTIFACT_BASE="iptables-forward-${VERSION}"
{
echo "version=${VERSION}"
echo "tag=${TAG}"
echo "title=${TITLE}"
echo "artifact_base=${ARTIFACT_BASE}"
echo "short_sha=${SHORT_SHA}"
echo "full_sha=${FULL_SHA}"
echo "build_time=${BUILD_TIME}"
} >> "$GITHUB_OUTPUT"
echo "准备构建: ${VERSION}"
- name: Ensure tag does not already exist
run: |
set -euo pipefail
TAG='${{ steps.ver.outputs.tag }}'
if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then
echo "::error::Tag ${TAG} 已存在于远端。请手动传入新的 version 输入。"
exit 1
fi
- name: Build release tarball
id: build
run: |
set -euo pipefail
NAME='${{ steps.ver.outputs.artifact_base }}'
mkdir -p "dist/${NAME}"
cp iptables-forward.sh install.sh README.md "dist/${NAME}/"
cp -r lib "dist/${NAME}/"
[[ -f LICENSE ]] && cp LICENSE "dist/${NAME}/" || true
chmod 755 "dist/${NAME}/iptables-forward.sh" "dist/${NAME}/install.sh"
tar -czf "dist/${NAME}.tar.gz" -C dist "${NAME}"
( cd dist && sha256sum "${NAME}.tar.gz" > "${NAME}.tar.gz.sha256" )
ls -la dist/
- name: Generate changelog
id: changelog
run: |
set -euo pipefail
PREV_TAG=$(git tag --list 'v*' --sort=-creatordate | head -n 1 || true)
{
echo "## 构建信息"
echo ""
echo "- **版本**: \`${{ steps.ver.outputs.version }}\`"
echo "- **提交**: \`${{ steps.ver.outputs.full_sha }}\`"
echo "- **构建时间 (UTC)**: ${{ steps.ver.outputs.build_time }}"
echo "- **触发者**: @${{ github.actor }}"
echo ""
echo "## 变更记录"
echo ""
if [[ -n "${PREV_TAG}" ]]; then
echo "自 \`${PREV_TAG}\` 以来的提交:"
echo ""
git log "${PREV_TAG}..HEAD" --pretty='- %s (`%h`)' --no-merges || true
else
echo "首次发布,近 30 条提交:"
echo ""
git log -30 --pretty='- %s (`%h`)' --no-merges
fi
echo ""
echo "## 安装"
echo ""
echo '```bash'
echo "# 下载"
echo "wget ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.ver.outputs.tag }}/${{ steps.ver.outputs.artifact_base }}.tar.gz"
echo "wget ${{ github.server_url }}/${{ github.repository }}/releases/download/${{ steps.ver.outputs.tag }}/${{ steps.ver.outputs.artifact_base }}.tar.gz.sha256"
echo ""
echo "# 校验"
echo "sha256sum -c ${{ steps.ver.outputs.artifact_base }}.tar.gz.sha256"
echo ""
echo "# 解压并安装 (可选)"
echo "tar -xzf ${{ steps.ver.outputs.artifact_base }}.tar.gz"
echo "cd ${{ steps.ver.outputs.artifact_base }}"
echo "sudo ./install.sh # 链接到 /usr/local/bin/iptables-forward"
echo ""
echo "# 直接运行"
echo "sudo ./iptables-forward.sh"
echo '```'
} > dist/RELEASE_NOTES.md
cat dist/RELEASE_NOTES.md
- name: Create tag and Release via Gitea API
env:
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITEA_URL: ${{ github.server_url }}
REPO: ${{ github.repository }}
TAG: ${{ steps.ver.outputs.tag }}
TITLE: ${{ steps.ver.outputs.title }}
SHA: ${{ steps.ver.outputs.full_sha }}
ARTIFACT_BASE: ${{ steps.ver.outputs.artifact_base }}
PRERELEASE: ${{ inputs.prerelease }}
DRAFT: ${{ inputs.draft }}
run: |
set -euo pipefail
BODY=$(jq -Rs . < dist/RELEASE_NOTES.md)
PAYLOAD=$(jq -nc \
--arg tag "$TAG" \
--arg sha "$SHA" \
--arg name "$TITLE" \
--argjson body "$BODY" \
--argjson prerelease "$PRERELEASE" \
--argjson draft "$DRAFT" \
'{tag_name: $tag, target_commitish: $sha, name: $name, body: $body, prerelease: $prerelease, draft: $draft}')
echo "Creating release: $TAG"
RESP=$(curl -sSfL -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-H "Content-Type: application/json" \
-d "${PAYLOAD}" \
"${GITEA_URL}/api/v1/repos/${REPO}/releases")
RELEASE_ID=$(echo "$RESP" | jq -r '.id')
if [[ -z "${RELEASE_ID}" || "${RELEASE_ID}" == "null" ]]; then
echo "::error::创建 Release 失败。响应: ${RESP}"
exit 1
fi
echo "Release ID: ${RELEASE_ID}"
for asset in "dist/${ARTIFACT_BASE}.tar.gz" "dist/${ARTIFACT_BASE}.tar.gz.sha256"; do
fname=$(basename "$asset")
echo "Uploading $fname"
curl -sSfL -X POST \
-H "Authorization: token ${GITEA_TOKEN}" \
-F "attachment=@${asset};filename=${fname}" \
"${GITEA_URL}/api/v1/repos/${REPO}/releases/${RELEASE_ID}/assets?name=${fname}" \
> /dev/null
done
echo "完成: ${GITEA_URL}/${REPO}/releases/tag/${TAG}"
- name: Upload artifacts to workflow run (备份)
uses: actions/upload-artifact@v3
with:
name: ${{ steps.ver.outputs.artifact_base }}
path: |
dist/${{ steps.ver.outputs.artifact_base }}.tar.gz
dist/${{ steps.ver.outputs.artifact_base }}.tar.gz.sha256
dist/RELEASE_NOTES.md
retention-days: 30