Files
LowderPlay_cheburcheck/.github/workflows/release.yml
T
LowderPlay 63dff075c0 feat: probe autoupdate (#88)
* feat: autoupdate

* chore: bump version

* feat: publish installer

* fix: standalone builds

* ci: release docs

* fix: windows icmp socket

* docs: windows notice

* docs: remove line breaks
2026-08-29 00:22:08 +05:00

247 lines
8.6 KiB
YAML

name: Draft Release
on:
push:
tags: [ 'v*.*.*' ]
permissions:
actions: read
contents: write
concurrency:
group: draft-release-${{ github.ref_name }}
cancel-in-progress: false
jobs:
draft-release:
name: Draft GitHub release
runs-on: ubuntu-latest
steps:
- name: Collect build artifacts
uses: actions/github-script@v8
env:
TAG_NAME: ${{ github.ref_name }}
WORKFLOWS: |
Build Rust Application
Build Probe
with:
script: |
const fs = require('fs');
const path = require('path');
const owner = context.repo.owner;
const repo = context.repo.repo;
const tagName = process.env.TAG_NAME;
const workflows = process.env.WORKFLOWS
.split(/\r?\n/)
.map((name) => name.trim())
.filter(Boolean);
const targetSha = context.sha;
const outDir = path.join(process.cwd(), 'artifact-archives');
const pollDelayMs = 30_000;
const timeoutMs = 30 * 60 * 1000;
fs.mkdirSync(outDir, { recursive: true });
async function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
async function findWorkflowRun(workflowName) {
const startedAt = Date.now();
while (Date.now() - startedAt < timeoutMs) {
const runs = await github.paginate(
github.rest.actions.listWorkflowRunsForRepo,
{
owner,
repo,
head_sha: targetSha,
event: 'push',
per_page: 100,
},
);
const run = runs.find((candidate) =>
candidate.name === workflowName &&
candidate.head_sha === targetSha &&
candidate.head_branch === tagName
);
if (run?.status === 'completed') {
if (run.conclusion === 'success') {
return run;
}
throw new Error(
`${workflowName} completed with conclusion ${run.conclusion}: ${run.html_url}`,
);
}
core.info(
run
? `${workflowName} is ${run.status}; waiting for completion.`
: `Waiting for ${workflowName} to start for ${tagName}.`,
);
await sleep(pollDelayMs);
}
throw new Error(`Timed out waiting for ${workflowName} on ${tagName}.`);
}
for (const workflowName of workflows) {
const run = await findWorkflowRun(workflowName);
core.info(`Downloading artifacts from ${workflowName}: ${run.html_url}`);
const artifacts = await github.paginate(
github.rest.actions.listWorkflowRunArtifacts,
{
owner,
repo,
run_id: run.id,
per_page: 100,
},
);
for (const artifact of artifacts.filter((item) => !item.expired)) {
if (artifact.name.endsWith('.dockerbuild')) {
core.info(`Skipping Docker build record artifact ${artifact.name}`);
continue;
}
const archive = await github.rest.actions.downloadArtifact({
owner,
repo,
artifact_id: artifact.id,
archive_format: 'zip',
});
const artifactPath = path.join(outDir, `${artifact.name}.zip`);
fs.writeFileSync(artifactPath, Buffer.from(archive.data));
core.info(`Saved ${artifactPath}`);
}
}
- name: Extract release assets
shell: bash
run: |
set -euo pipefail
mkdir -p release-artifacts
for archive in artifact-archives/*.zip; do
artifact_name="$(basename "$archive" .zip)"
extract_dir="$(mktemp -d)"
unzip -q "$archive" -d "$extract_dir"
while IFS= read -r -d '' file; do
filename="$(basename "$file")"
target="release-artifacts/$filename"
if [ -e "$target" ]; then
target="release-artifacts/${artifact_name}-${filename}"
fi
mv "$file" "$target"
done < <(find "$extract_dir" -type f -print0)
rm -rf "$extract_dir"
done
- name: Generate release body
uses: actions/github-script@v8
env:
TAG_NAME: ${{ github.ref_name }}
with:
script: |
const fs = require('fs');
const path = require('path');
const tag = process.env.TAG_NAME;
const files = fs.readdirSync('release-artifacts')
.filter((name) => fs.statSync(path.join('release-artifacts', name)).isFile())
.sort();
function describe(name) {
if (/^cheburchecker_.+_amd64\.deb$/.test(name)) {
return 'Пакет Cheburchecker для Debian Linux x86-64.';
}
if (/^cheburchecker_.+_arm64\.deb$/.test(name)) {
return 'Пакет Cheburchecker для Debian Linux ARM64.';
}
if (/^cheburprobe-.+-linux-amd64$/.test(name)) {
return 'Cheburprobe для Linux x86-64.';
}
if (/^cheburprobe-.+-linux-arm64$/.test(name)) {
return 'Cheburprobe для Linux ARM64.';
}
if (/^cheburprobe-.+-windows-x86_64\.exe$/.test(name)) {
return 'Cheburprobe для Windows x86-64.';
}
if (/^cheburprobe_.+_amd64\.deb$/.test(name)) {
return 'Пакет Cheburprobe для Debian Linux x86-64 с сервисом и автообновлением.';
}
if (/^cheburprobe_.+_arm64\.deb$/.test(name)) {
return 'Пакет Cheburprobe для Debian Linux ARM64 с сервисом и автообновлением.';
}
if (/^cheburprobe-.+_.+\.apk$/.test(name)) {
return 'Пакет Cheburprobe для версий OpenWrt с пакетным менеджером APK (25.12+).';
}
if (/^luci-app-cheburprobe-.+\.apk$/.test(name)) {
return 'Интерфейс LuCI для APK-пакета Cheburprobe.';
}
if (/^cheburprobe_.+_.+\.ipk$/.test(name)) {
return 'Пакет Cheburprobe для версий OpenWrt с пакетным менеджером opkg.';
}
if (/^luci-app-cheburprobe_.+_all\.ipk$/.test(name)) {
return 'Интерфейс LuCI для IPK-пакета Cheburprobe.';
}
return 'Файл релиза.';
}
const baseUrl = [
'https://github.com',
encodeURIComponent(context.repo.owner),
encodeURIComponent(context.repo.repo),
'releases',
'download',
encodeURIComponent(tag),
].join('/');
const sourceBaseUrl = [
'https://github.com',
encodeURIComponent(context.repo.owner),
encodeURIComponent(context.repo.repo),
'blob',
encodeURIComponent(tag),
].join('/');
const rows = files.map((name) => {
const url = baseUrl + '/' + encodeURIComponent(name);
return '| [`' + name + '`](' + url + ') | ' + describe(name) + ' |';
});
const body = [
'## Документация',
'',
'- [Cheburprobe](' + sourceBaseUrl + '/probe/README.md)',
'- [Cheburchecker](' + sourceBaseUrl + '/reporter/README.md)',
'',
'## Файлы релиза',
'',
'| Файл | Описание |',
'| --- | --- |',
...rows,
'',
].join('\n');
fs.writeFileSync('release-body.md', body);
- name: Publish draft release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}
draft: true
body_path: release-body.md
fail_on_unmatched_files: true
files: release-artifacts/*