Skip to content

Commit 858d202

Browse files
committed
Improve workflows
1 parent ac16554 commit 858d202

4 files changed

Lines changed: 191 additions & 34 deletions

File tree

.github/workflows/beta.yml

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
branches: [ Beta ]
77
workflow_dispatch:
88

9+
concurrency:
10+
group: openvcs-beta
11+
cancel-in-progress: true
12+
913
permissions:
1014
contents: write
1115
actions: write
@@ -17,8 +21,31 @@ env:
1721
SCCACHE_CACHE_SIZE: ${{ vars.SSCCACHE_SIZE }}
1822

1923
jobs:
24+
prepare-release:
25+
name: Clean existing rolling release
26+
runs-on: ubuntu-22.04
27+
permissions:
28+
contents: write
29+
steps:
30+
- name: Remove existing 'openvcs-beta' release & tag
31+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
32+
with:
33+
script: |
34+
const owner = context.repo.owner;
35+
const repo = context.repo.repo;
36+
const tag = 'openvcs-beta';
37+
const releases = await github.paginate(github.rest.repos.listReleases, { owner, repo, per_page: 100 });
38+
const rel = releases.find(r => r.tag_name === tag);
39+
if (rel) await github.rest.repos.deleteRelease({ owner, repo, release_id: rel.id });
40+
try {
41+
await github.rest.git.deleteRef({ owner, repo, ref: `tags/${tag}` });
42+
} catch (e) {
43+
if (e.status !== 422) throw e;
44+
}
45+
2046
beta:
2147
name: Build & publish Beta
48+
needs: prepare-release
2249
strategy:
2350
fail-fast: false
2451
matrix:
@@ -94,21 +121,8 @@ jobs:
94121
- name: Cargo clippy
95122
run: cargo clippy --all-targets -- -D warnings
96123

97-
- name: Remove existing 'openvcs-beta' release & tag
98-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
99-
with:
100-
script: |
101-
const owner = context.repo.owner;
102-
const repo = context.repo.repo;
103-
const tag = 'openvcs-beta';
104-
const releases = await github.paginate(github.rest.repos.listReleases, { owner, repo, per_page: 100 });
105-
const rel = releases.find(r => r.tag_name === tag);
106-
if (rel) await github.rest.repos.deleteRelease({ owner, repo, release_id: rel.id });
107-
try {
108-
await github.rest.git.deleteRef({ owner, repo, ref: `tags/${tag}` });
109-
} catch (e) {
110-
if (e.status !== 422) throw e;
111-
}
124+
- name: Patch version for beta prerelease
125+
run: node scripts/bump-tauri-version.js beta
112126

113127
- name: Write channel Tauri config override
114128
env:
@@ -134,6 +148,6 @@ jobs:
134148
Date (UTC): ${{ steps.meta.outputs.date }}
135149
Commit: ${{ github.sha }} (${{ env.TARGET_REF }}@${{ steps.meta.outputs.short_sha }})
136150
Runner: ${{ runner.os }} • Run #${{ github.run_number }}
137-
releaseDraft: true
151+
releaseDraft: false
138152
prerelease: true
139153
args: ${{ format('{0} --config {1}/tauri.channel.conf.json', matrix.args || '', runner.temp) }}

.github/workflows/nightly.yml

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ on:
1313
required: false
1414
default: false
1515

16+
concurrency:
17+
group: openvcs-nightly
18+
cancel-in-progress: true
19+
1620
# Default to least privilege; override per-job as needed
1721
permissions:
1822
contents: read
@@ -71,9 +75,33 @@ jobs:
7175
echo "ahead_count=$AHEAD" >> "$GITHUB_OUTPUT"
7276
fi
7377
78+
prepare-release:
79+
name: Clean existing rolling release
80+
needs: check-changes
81+
if: needs.check-changes.outputs.changed == 'true' || (github.event_name == 'workflow_dispatch' && (inputs.force == true || github.event.inputs.force == 'true'))
82+
runs-on: ubuntu-22.04
83+
permissions:
84+
contents: write
85+
steps:
86+
- name: Remove existing 'openvcs-nightly' release & tag
87+
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
88+
with:
89+
script: |
90+
const owner = context.repo.owner;
91+
const repo = context.repo.repo;
92+
const tag = 'openvcs-nightly';
93+
const releases = await github.paginate(github.rest.repos.listReleases, { owner, repo, per_page: 100 });
94+
const rel = releases.find(r => r.tag_name === tag);
95+
if (rel) await github.rest.repos.deleteRelease({ owner, repo, release_id: rel.id });
96+
try {
97+
await github.rest.git.deleteRef({ owner, repo, ref: `tags/${tag}` });
98+
} catch (e) {
99+
if (e.status !== 422) throw e;
100+
}
101+
74102
nightly:
75103
name: Build & publish Nightly (only if changed)
76-
needs: check-changes
104+
needs: [check-changes, prepare-release]
77105
if: needs.check-changes.outputs.changed == 'true' || (github.event_name == 'workflow_dispatch' && (inputs.force == true || github.event.inputs.force == 'true'))
78106
permissions:
79107
contents: write # create/delete release + tag
@@ -202,21 +230,8 @@ jobs:
202230
run: cargo clippy --all-targets -- -D warnings
203231

204232
# ---------- Reset rolling tag (optional but keeps things tidy) ----------
205-
- name: Remove existing 'openvcs-nightly' release & tag (if any)
206-
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
207-
with:
208-
script: |
209-
const owner = context.repo.owner;
210-
const repo = context.repo.repo;
211-
const tag = 'openvcs-nightly';
212-
const releases = await github.paginate(github.rest.repos.listReleases, { owner, repo, per_page: 100 });
213-
const rel = releases.find(r => r.tag_name === tag);
214-
if (rel) await github.rest.repos.deleteRelease({ owner, repo, release_id: rel.id });
215-
try {
216-
await github.rest.git.deleteRef({ owner, repo, ref: `tags/${tag}` });
217-
} catch (e) {
218-
if (e.status !== 422) throw e;
219-
}
233+
- name: Patch version for nightly prerelease
234+
run: node scripts/bump-tauri-version.js alpha
220235

221236
- name: Write channel Tauri config override
222237
env:

Backend/build.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ fn main() {
341341
println!("cargo:rustc-env=GIT_DESCRIBE={}", describe);
342342

343343
// Dev builds (local/nightly) should show git branch+hash (+dirty) as version metadata.
344-
// Official production builds should show the real package version.
344+
// Official production builds and CI-patched prerelease builds should show the package version.
345345
//
346346
// Rules:
347347
// - `OPENVCS_OFFICIAL_RELEASE=1` forces "official" behavior.
@@ -376,7 +376,7 @@ fn main() {
376376

377377
let official = is_truthy_env("OPENVCS_OFFICIAL_RELEASE") || (head_is_version_tag && !dirty);
378378

379-
let version = if official {
379+
let version = if official || pkg_version.contains('-') {
380380
pkg_version.clone()
381381
} else {
382382
let branch_ident = sanitize_semver_ident(&branch);

scripts/bump-tauri-version.js

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright © 2025-2026 OpenVCS Contributors
2+
// SPDX-License-Identifier: GPL-3.0-or-later
3+
4+
/**
5+
* Bumps the Tauri package version for CI prerelease builds.
6+
*
7+
* Uses cargo metadata to read the current version from Backend/Cargo.toml,
8+
* increments the patch component, appends a prerelease suffix with the GitHub
9+
* run number, and writes back to the manifest.
10+
*
11+
* Usage: node scripts/bump-tauri-version.js <channel>
12+
* channel: 'alpha' for nightly, 'beta' for beta releases
13+
*
14+
* Environment:
15+
* GITHUB_RUN_NUMBER - used for monotonic versioning (set by GitHub Actions)
16+
*/
17+
18+
const fs = require('fs');
19+
const path = require('path');
20+
const { execFileSync } = require('child_process');
21+
22+
const CARGO_PATH = path.resolve(__dirname, '../Backend/Cargo.toml');
23+
24+
/**
25+
* Read the package version using cargo metadata (TOML-aware).
26+
* @returns {string} Current version string (e.g., "0.3.0")
27+
*/
28+
function readVersion() {
29+
const metadata = JSON.parse(
30+
execFileSync('cargo', [
31+
'metadata',
32+
'--no-deps',
33+
'--format-version',
34+
'1',
35+
'--manifest-path',
36+
CARGO_PATH,
37+
], { encoding: 'utf8' })
38+
);
39+
40+
const version = metadata.packages?.find((pkg) => {
41+
return path.resolve(pkg.manifest_path) === CARGO_PATH;
42+
})?.version;
43+
if (!version) {
44+
throw new Error('Could not read package version from cargo metadata');
45+
}
46+
return version;
47+
}
48+
49+
/**
50+
* Compute the new prerelease version.
51+
* @param {string} currentVersion - Current semver (e.g., "0.3.0")
52+
* @param {string} channel - Prerelease channel ('alpha' or 'beta')
53+
* @returns {string} New version (e.g., "0.3.1-alpha.1234")
54+
*/
55+
function computeNewVersion(currentVersion, channel) {
56+
// Strip any existing prerelease suffix (e.g., "0.3.0-alpha.1" -> "0.3.0")
57+
const baseVersion = currentVersion.split('-')[0];
58+
const parts = baseVersion.split('.');
59+
60+
if (parts.length !== 3) {
61+
throw new Error(`Invalid semver format: ${currentVersion}`);
62+
}
63+
64+
const major = parseInt(parts[0], 10);
65+
const minor = parseInt(parts[1], 10);
66+
const patch = parseInt(parts[2], 10) + 1; // bump patch for next release
67+
68+
// Use GITHUB_RUN_NUMBER for monotonic versioning
69+
// Reruns of the same workflow keep the same version to avoid mixed artifacts
70+
const runNumber = process.env.GITHUB_RUN_NUMBER || '0';
71+
72+
return `${major}.${minor}.${patch}-${channel}.${runNumber}`;
73+
}
74+
75+
/**
76+
* Write the new version back to the `[package]` section in Cargo.toml.
77+
* @param {string} newVersion - New version string to write
78+
*/
79+
function writeVersion(newVersion) {
80+
const content = fs.readFileSync(CARGO_PATH, 'utf8');
81+
const lines = content.split(/\r?\n/);
82+
let inPackageSection = false;
83+
let replaced = false;
84+
85+
const newContent = lines.map((line) => {
86+
const sectionMatch = line.match(/^\s*\[([^\]]+)\]\s*$/);
87+
if (sectionMatch) {
88+
inPackageSection = sectionMatch[1].trim() === 'package';
89+
return line;
90+
}
91+
92+
if (inPackageSection && /^\s*version\s*=\s*".*"\s*$/.test(line)) {
93+
if (replaced) {
94+
throw new Error('Found multiple package version entries in Cargo.toml');
95+
}
96+
replaced = true;
97+
return `version = "${newVersion}"`;
98+
}
99+
100+
return line;
101+
}).join('\n');
102+
103+
if (!replaced) {
104+
throw new Error('Could not find package version in Cargo.toml');
105+
}
106+
107+
fs.writeFileSync(CARGO_PATH, newContent);
108+
}
109+
110+
function main() {
111+
const channel = process.argv[2];
112+
113+
if (!channel || !['alpha', 'beta'].includes(channel)) {
114+
console.error('Usage: node bump-tauri-version.js <alpha|beta>');
115+
process.exit(1);
116+
}
117+
118+
const currentVersion = readVersion();
119+
console.log('Current version:', currentVersion);
120+
121+
const newVersion = computeNewVersion(currentVersion, channel);
122+
console.log('New version:', newVersion);
123+
124+
writeVersion(newVersion);
125+
console.log('Updated Backend/Cargo.toml');
126+
}
127+
128+
main();

0 commit comments

Comments
 (0)