Repository navigation
135 lines (128 loc) · 6.66 KB
/
Copy pathrelease.yml
File metadata and controls
135 lines (128 loc) · 6.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# Релиз: поднять version в package.json, затем git tag vX.Y.Z && git push --tags
# 1) create — черновик релиза с текстом из build/release-notes.md;
# 2) build — Windows (установщик + portable), macOS (dmg + zip, Intel и Apple Silicon), Linux (AppImage + deb)
# собираются параллельно и загружаются в этот черновик;
# 3) publish — черновик публикуется; установленные копии подхватывают обновление (latest.yml / latest-mac.yml);
# 4) virustotal — .exe проверяются на VirusTotal, ссылки с результатом дописываются в описание (секрет VT_API_KEY).
# Подпись Windows:
# • SignPath (бесплатно для open source, см. «Code signing policy» в README): включается, когда в репозитории
# заданы переменная SIGNPATH_ORGANIZATION_ID и секрет SIGNPATH_API_TOKEN (слаги — переменными SIGNPATH_*).
# Сборка без подписи → SignPath (каждый релиз подтверждается вручную) → подписанные exe, новые latest.yml и
# блок-карта загружаются в черновик (tools/release-signed.js);
# • или свой сертификат: секреты WIN_CSC_LINK (pfx в base64) и WIN_CSC_KEY_PASSWORD.
name: Release
on:
push:
tags: ['v*']
workflow_dispatch:
permissions:
contents: write
jobs:
create:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="${GITHUB_REF_NAME}"
VER="${TAG#v}"
if curl -sf -H "Authorization: Bearer $GH_TOKEN" "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" > /dev/null; then
echo "release ${TAG} already exists"; exit 0
fi
jq -n --arg tag "$TAG" --arg name "Caskit ${VER}" --rawfile body build/release-notes.md \
'{tag_name: $tag, name: $name, body: $body, draft: true}' > release.json
curl -sf -X POST -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${GITHUB_REPOSITORY}/releases" -d @release.json > /dev/null
build:
needs: create
strategy:
fail-fast: false
matrix:
include:
- os: windows-latest
args: --win nsis portable --x64 -c.win.signAndEditExecutable=true
- os: macos-latest
args: --mac dmg zip --x64 --arm64
- os: ubuntu-latest
args: --linux AppImage deb --x64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- name: Build and upload to the draft release
if: matrix.os != 'windows-latest' || vars.SIGNPATH_ORGANIZATION_ID == ''
shell: bash # в PowerShell аргумент -c.win.… разбирается как путь к файлу конфигурации
run: npx electron-builder ${{ matrix.args }} --publish always
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CSC_IDENTITY_AUTO_DISCOVERY: 'false' # без платной подписи Apple; см. README про первый запуск на macOS
WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
WIN_CSC_KEY_PASSWORD: ${{ secrets.WIN_CSC_KEY_PASSWORD }}
# ---- Windows + SignPath
- name: Build (unsigned, for SignPath)
if: matrix.os == 'windows-latest' && vars.SIGNPATH_ORGANIZATION_ID != ''
shell: bash
run: npx electron-builder ${{ matrix.args }} --publish never
- name: Upload unsigned build for SignPath
if: matrix.os == 'windows-latest' && vars.SIGNPATH_ORGANIZATION_ID != ''
id: unsigned
uses: actions/upload-artifact@v4
with:
name: windows-unsigned
if-no-files-found: error
path: |
dist/Caskit-Setup-*.exe
dist/Caskit-*-portable.exe
- name: Sign with SignPath
if: matrix.os == 'windows-latest' && vars.SIGNPATH_ORGANIZATION_ID != ''
uses: signpath/github-action-submit-signing-request@v2
with:
api-token: ${{ secrets.SIGNPATH_API_TOKEN }}
organization-id: ${{ vars.SIGNPATH_ORGANIZATION_ID }}
project-slug: ${{ vars.SIGNPATH_PROJECT_SLUG || 'caskit' }}
signing-policy-slug: ${{ vars.SIGNPATH_SIGNING_POLICY_SLUG || 'release-signing' }}
artifact-configuration-slug: ${{ vars.SIGNPATH_ARTIFACT_CONFIGURATION_SLUG }}
github-artifact-id: ${{ steps.unsigned.outputs.artifact-id }}
wait-for-completion: true
wait-for-completion-timeout-in-seconds: 21600 # релиз подтверждается вручную в SignPath
output-artifact-directory: signed
- name: Upload signed build to the draft release
if: matrix.os == 'windows-latest' && vars.SIGNPATH_ORGANIZATION_ID != ''
shell: bash
run: node tools/release-signed.js signed
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish:
needs: build
runs-on: ubuntu-latest
steps:
- name: Publish the release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
ID=$(curl -sf -H "Authorization: Bearer $GH_TOKEN" "https://api.github.com/repos/${GITHUB_REPOSITORY}/releases?per_page=20" \
| jq -r --arg tag "${GITHUB_REF_NAME}" '.[] | select(.tag_name == $tag) | .id' | head -1)
test -n "$ID"
curl -sf -X PATCH -H "Authorization: Bearer $GH_TOKEN" -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/${ID}" -d '{"draft": false, "make_latest": "true"}' > /dev/null
# Проверка .exe на VirusTotal и ссылки с результатом в описании релиза (нужен секрет VT_API_KEY —
# бесплатный ключ: virustotal.com → профиль → API key). Без ключа шаг просто пропускается.
virustotal:
needs: publish
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Scan the release on VirusTotal
run: node tools/virustotal.js "${GITHUB_REF_NAME}"
env:
VT_API_KEY: ${{ secrets.VT_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}