Skip to content

Commit 2d4c539

Browse files
mcpolo99RandomCrocodile
andauthored
chore: manual + monthly release workflow instead of release-on-push (#92)
Releases are no longer cut automatically on every push to main. A dedicated release.yml handles them two ways, both minute-conscious: - Manual: workflow_dispatch builds, tags and publishes a GitHub Release from main on demand (with a force input to release even without new commits). - Monthly: a cron on the 1st runs a cheap Ubuntu check that compares main to the last v* tag and only spends the Windows build+publish when there are new commits. ci.yml is reduced to build validation: removed the push-to-main release job and the now-dead dev-release job (develop no longer triggers ci after the gating in #90), and dropped the push trigger. docs/building.md updated. This change is workflow + docs only, nothing to build or test. [skip ci] Co-authored-by: RandomCrocodile <mawi@polosab.com>
1 parent d5f2150 commit 2d4c539

3 files changed

Lines changed: 184 additions & 113 deletions

File tree

.github/workflows/ci.yml

Lines changed: 10 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
name: ci
22

3-
# GitHub Actions minutes are limited, so this build runs automatically only where
4-
# it matters: a PR into `main` (the develop -> main release gate) and pushes to
5-
# `main` (the release itself). For PRs into `develop`, day-to-day validation is
6-
# done with scripts/local-ci.sh; a run here happens only when an admin adds the
7-
# `run-ci` label (re-add it to trigger each run) or dispatches the workflow
8-
# manually. See the `if:` on the build job below.
3+
# Build validation. GitHub Actions minutes are limited, so this runs automatically
4+
# only for PRs into `main` (the develop -> main gate). For PRs into `develop`,
5+
# day-to-day validation is done with scripts/local-ci.sh; a run here happens only
6+
# when an admin adds the `run-ci` label (re-add it to trigger each run) or
7+
# dispatches the workflow manually. See the `if:` on the build job below.
8+
#
9+
# This workflow does NOT publish releases — that is handled by release.yml
10+
# (manual dispatch + a monthly check for new commits on main).
911
on:
10-
push:
11-
branches: [main]
12-
paths-ignore: ['**.md', 'docs/**', 'LICENSE*']
1312
pull_request:
1413
branches: [main, develop]
1514
types: [opened, synchronize, reopened, labeled]
@@ -22,11 +21,10 @@ concurrency:
2221

2322
jobs:
2423
build:
25-
# Auto for main (PRs into it + release pushes) and manual dispatch; for develop
26-
# PRs only when an admin adds the `run-ci` label.
24+
# Auto for PRs into main and manual dispatch; for develop PRs only when an
25+
# admin adds the `run-ci` label.
2726
if: >-
2827
github.event_name == 'workflow_dispatch' ||
29-
github.event_name == 'push' ||
3028
github.base_ref == 'main' ||
3129
(github.event.action == 'labeled' && github.event.label.name == 'run-ci')
3230
runs-on: windows-2025
@@ -103,101 +101,3 @@ jobs:
103101
ConfuserEx-GUI.zip
104102
ConfuserEx.zip
105103
Confuser.MSBuild.Tasks/bin/Release/*.nupkg
106-
107-
# Dev build: on push to develop branch
108-
dev-release:
109-
needs: build
110-
if: github.event_name == 'push' && github.ref == 'refs/heads/develop'
111-
runs-on: windows-2025
112-
timeout-minutes: 5
113-
permissions:
114-
contents: write
115-
steps:
116-
- uses: actions/checkout@v5
117-
with:
118-
fetch-depth: 0
119-
120-
- name: Install nbgv
121-
run: dotnet tool install -g nbgv
122-
123-
- name: Compute version
124-
id: version
125-
shell: pwsh
126-
run: |
127-
$ver = nbgv get-version -v NuGetPackageVersion
128-
echo "VERSION=$ver" >> $env:GITHUB_OUTPUT
129-
130-
- name: Download artifacts
131-
uses: actions/download-artifact@v5
132-
with:
133-
name: confuserex-packages
134-
135-
- name: Create or update dev release
136-
uses: softprops/action-gh-release@v2
137-
with:
138-
tag_name: dev-latest
139-
name: "Dev build v${{ steps.version.outputs.VERSION }}"
140-
prerelease: true
141-
make_latest: false
142-
body: |
143-
**Development build** — for testing only, not production use.
144-
145-
Version: `${{ steps.version.outputs.VERSION }}`
146-
Branch: `develop`
147-
Commit: ${{ github.sha }}
148-
149-
Download the binaries below to test recent fixes and features before they are included in a stable release.
150-
files: |
151-
ConfuserEx-CLI.zip
152-
ConfuserEx-GUI.zip
153-
ConfuserEx.zip
154-
*.nupkg
155-
156-
# Release: only on PR merge to main
157-
release:
158-
needs: build
159-
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
160-
runs-on: windows-2025
161-
timeout-minutes: 5
162-
permissions:
163-
contents: write
164-
steps:
165-
- uses: actions/checkout@v5
166-
with:
167-
fetch-depth: 0
168-
169-
- name: Install nbgv
170-
run: dotnet tool install -g nbgv
171-
172-
- name: Compute version
173-
id: version
174-
shell: pwsh
175-
run: |
176-
$ver = nbgv get-version -v NuGetPackageVersion
177-
echo "VERSION=$ver" >> $env:GITHUB_OUTPUT
178-
179-
- name: Configure git identity
180-
run: |
181-
git config user.name "github-actions[bot]"
182-
git config user.email "github-actions[bot]@users.noreply.github.com"
183-
184-
- name: Create release tag
185-
run: |
186-
git tag -a "v${{ steps.version.outputs.VERSION }}" -m "Release ${{ steps.version.outputs.VERSION }}"
187-
git push origin "v${{ steps.version.outputs.VERSION }}"
188-
189-
- name: Download artifacts
190-
uses: actions/download-artifact@v5
191-
with:
192-
name: confuserex-packages
193-
194-
- name: Create GitHub Release
195-
uses: softprops/action-gh-release@v2
196-
with:
197-
tag_name: v${{ steps.version.outputs.VERSION }}
198-
name: v${{ steps.version.outputs.VERSION }}
199-
files: |
200-
ConfuserEx-CLI.zip
201-
ConfuserEx-GUI.zip
202-
ConfuserEx.zip
203-
*.nupkg

.github/workflows/release.yml

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
name: release
2+
3+
# GitHub Actions minutes are limited, so releases are NOT cut automatically on
4+
# every push to main. Instead:
5+
# - Run this workflow manually (Actions tab -> release -> Run workflow) to build
6+
# and publish a release from main on demand.
7+
# - On the 1st of each month it checks main for commits since the last release
8+
# tag and only spends the (expensive) Windows build when there are new changes.
9+
#
10+
# The check job runs on a cheap Ubuntu runner, so a monthly run with nothing new
11+
# costs only a few seconds and publishes nothing.
12+
on:
13+
workflow_dispatch:
14+
inputs:
15+
force:
16+
description: "Release even if there are no new commits since the last release tag"
17+
type: boolean
18+
default: false
19+
schedule:
20+
- cron: "0 6 1 * *" # 06:00 UTC on the 1st of every month
21+
22+
concurrency:
23+
group: release
24+
cancel-in-progress: false
25+
26+
permissions:
27+
contents: write
28+
29+
jobs:
30+
check:
31+
name: Check main for new commits
32+
runs-on: ubuntu-latest
33+
outputs:
34+
should_release: ${{ steps.decide.outputs.should_release }}
35+
steps:
36+
- uses: actions/checkout@v5
37+
with:
38+
ref: main
39+
fetch-depth: 0
40+
fetch-tags: true
41+
42+
- name: Decide whether to release
43+
id: decide
44+
shell: bash
45+
run: |
46+
last_tag=$(git tag --list 'v*' --sort=-v:refname | head -n1)
47+
if [ -z "$last_tag" ]; then
48+
echo "No release tag found — treating as first release."
49+
echo "should_release=true" >> "$GITHUB_OUTPUT"
50+
exit 0
51+
fi
52+
53+
behind=$(git rev-list "$last_tag"..HEAD --count)
54+
echo "Last release: $last_tag — $behind new commit(s) on main since then."
55+
56+
if [ "${{ github.event_name }}" = "workflow_dispatch" ] && [ "${{ inputs.force }}" = "true" ]; then
57+
echo "Manual dispatch with force=true — releasing."
58+
echo "should_release=true" >> "$GITHUB_OUTPUT"
59+
elif [ "$behind" -gt 0 ]; then
60+
echo "New commits present — releasing."
61+
echo "should_release=true" >> "$GITHUB_OUTPUT"
62+
else
63+
echo "No new commits since $last_tag — skipping. (Use force=true to release anyway.)"
64+
echo "should_release=false" >> "$GITHUB_OUTPUT"
65+
fi
66+
67+
release:
68+
name: Build and publish release
69+
needs: check
70+
if: needs.check.outputs.should_release == 'true'
71+
runs-on: windows-2025
72+
timeout-minutes: 15
73+
permissions:
74+
contents: write
75+
env:
76+
NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
77+
steps:
78+
- uses: actions/checkout@v5
79+
with:
80+
ref: main
81+
fetch-depth: 0
82+
83+
- name: Setup MSBuild
84+
uses: microsoft/setup-msbuild@v2
85+
86+
- name: Cache NuGet packages
87+
uses: actions/cache@v4
88+
with:
89+
path: ${{ github.workspace }}/.nuget/packages
90+
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.vcxproj') }}
91+
restore-keys: |
92+
${{ runner.os }}-nuget-
93+
94+
- name: Install nbgv
95+
run: dotnet tool install -g nbgv
96+
97+
- name: Compute version
98+
id: version
99+
shell: pwsh
100+
run: |
101+
$ver = nbgv get-version -v NuGetPackageVersion
102+
echo "VERSION=$ver" >> $env:GITHUB_OUTPUT
103+
Write-Host "Version: $ver"
104+
105+
- name: Restore
106+
run: msbuild Confuser2.sln -t:Restore -verbosity:minimal
107+
108+
- name: Build
109+
run: msbuild Confuser2.sln -p:Configuration=Release -verbosity:minimal
110+
111+
- name: Package CLI
112+
shell: pwsh
113+
run: |
114+
$src = 'Confuser.CLI/bin/Release/net10.0'
115+
Get-ChildItem $src -Exclude '*.pdb','*.xml' | Compress-Archive -DestinationPath 'ConfuserEx-CLI.zip'
116+
Write-Host "Created ConfuserEx-CLI.zip"
117+
118+
- name: Package GUI
119+
shell: pwsh
120+
run: |
121+
$src = 'ConfuserEx/bin/Release/net10.0-windows'
122+
Get-ChildItem $src -Exclude '*.pdb','*.xml' | Compress-Archive -DestinationPath 'ConfuserEx-GUI.zip'
123+
Write-Host "Created ConfuserEx-GUI.zip"
124+
125+
- name: Package combined
126+
shell: pwsh
127+
run: |
128+
$tmp = 'combined'
129+
New-Item -ItemType Directory -Path $tmp -Force | Out-Null
130+
Copy-Item 'Confuser.CLI/bin/Release/net10.0/*' $tmp -Exclude '*.pdb','*.xml' -Recurse
131+
Copy-Item 'ConfuserEx/bin/Release/net10.0-windows/*' $tmp -Exclude '*.pdb','*.xml' -Recurse -Force
132+
Get-ChildItem $tmp | Compress-Archive -DestinationPath 'ConfuserEx.zip'
133+
Remove-Item $tmp -Recurse -Force
134+
Write-Host "Created ConfuserEx.zip"
135+
136+
- name: Configure git identity
137+
run: |
138+
git config user.name "github-actions[bot]"
139+
git config user.email "github-actions[bot]@users.noreply.github.com"
140+
141+
- name: Create release tag
142+
shell: bash
143+
run: |
144+
tag="v${{ steps.version.outputs.VERSION }}"
145+
if git rev-parse "$tag" >/dev/null 2>&1; then
146+
echo "Tag $tag already exists — skipping tag creation."
147+
else
148+
git tag -a "$tag" -m "Release ${{ steps.version.outputs.VERSION }}"
149+
git push origin "$tag"
150+
fi
151+
152+
- name: Create GitHub Release
153+
uses: softprops/action-gh-release@v2
154+
with:
155+
tag_name: v${{ steps.version.outputs.VERSION }}
156+
name: v${{ steps.version.outputs.VERSION }}
157+
files: |
158+
ConfuserEx-CLI.zip
159+
ConfuserEx-GUI.zip
160+
ConfuserEx.zip
161+
Confuser.MSBuild.Tasks/bin/Release/*.nupkg

docs/building.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,15 +72,25 @@ which mirrors the same build, test and coverage steps offline.
7272

7373
| Workflow | Trigger | Purpose |
7474
|----------|---------|---------|
75-
| `ci.yml` | PR into `main` + push to `main` (release). Manual: `run-ci` label on a `develop` PR, or `workflow_dispatch` | Build, package, create releases |
75+
| `ci.yml` | PR into `main`. Manual: `run-ci` label on a `develop` PR, or `workflow_dispatch` | Build + package (validation only) |
7676
| `test.yml` | PR into `main`. Manual: `run-ci` label on a `develop` PR, or `workflow_dispatch` | Build, test, coverage report |
7777
| `lint.yml` | PR into `main`. Manual: `run-ci` label on a `develop` PR, or `workflow_dispatch` | Whitespace, style, Roslyn analyzers |
78+
| `release.yml` | Manual (`workflow_dispatch`) + monthly (1st of month) | Build, tag and publish a GitHub Release from `main` |
7879
| `codeql-analysis.yml` | Weekly + manual | Security analysis |
7980

8081
**PRs into `develop` do not run the cloud pipeline automatically** — validate them
8182
with `scripts/local-ci.sh`. To run a workflow on a specific `develop` PR anyway, an
8283
admin adds the `run-ci` label (re-add it to trigger each subsequent run) or
8384
dispatches the workflow manually from the Actions tab.
8485

85-
Releases are created by `ci.yml` when `develop` is merged into `main`. Versioning is
86-
handled by [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning) from `version.json`.
86+
### Releases
87+
88+
Releases are **not** cut automatically on push to `main`. `release.yml` handles them:
89+
90+
- **Manual** — Actions tab → **release****Run workflow** (on `main`). Builds, tags
91+
`v<version>`, and publishes a GitHub Release with the CLI/GUI/combined zips and the
92+
MSBuild-tasks nupkg. Use the `force` input to release even with no new commits.
93+
- **Monthly** — on the 1st of each month a cheap check compares `main` to the last
94+
`v*` tag and only runs the (expensive) build+publish when there are new commits.
95+
96+
Versioning is handled by [Nerdbank.GitVersioning](https://github.com/dotnet/Nerdbank.GitVersioning) from `version.json`.

0 commit comments

Comments
 (0)