Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 125 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ name: Release
# With "publish" unticked the workflow only builds and uploads the files as an artifact.
# The app's update check (UpdateService) reads these releases and looks for the
# ConsoleMode-Setup-*.exe / ConsoleMode-Portable-*.exe assets built here.
#
# "draft" (with "publish"): the release is created as a draft. Only people with write access see a draft:
# the app's update check doesn't, nothing goes to winget and the tag isn't created yet. Publishing the draft
# on GitHub creates the tag on the commit that was built, and winget.yml then sends it to winget.
#
# "legacy": a branch built next to this one (release/1.7-legacy: 1.6.2's interfaces, frozen) and attached to
# the same release as ConsoleMode-Legacy-*.exe. Those names don't start like the ones the update check and
# winget look for, so nobody is updated to Legacy.
on:
push:
tags:
Expand All @@ -20,17 +28,89 @@ on:
description: "Publish: create the tag and the GitHub release (only from main). Unticked, just build."
type: boolean
default: false
draft:
description: "Draft: with Publish, create the release as a draft (no update notice, no winget, no tag yet)."
type: boolean
default: false
legacy:
description: "Legacy: branch to build and attach as ConsoleMode-Legacy-*.exe (e.g. release/1.7-legacy). Empty: none."
required: false
default: ""

permissions:
contents: write
# The build job fetches the Legacy job's files of this same run.
actions: read

jobs:
# The Legacy build: the branch's own code, tests and publish script, with the version of this release.
legacy:
if: github.event_name == 'workflow_dispatch' && github.event.inputs.legacy != ''
runs-on: windows-latest
# It runs the code of a branch named at run time: read-only, and the token doesn't stay in the checkout.
# Its files reach the release through the artifact, attached by the build job.
permissions:
contents: read
steps:
- name: Checkout the Legacy branch
uses: actions/checkout@v7
Comment thread
pullfrog[bot] marked this conversation as resolved.
Resolved
with:
ref: ${{ github.event.inputs.legacy }}
persist-credentials: false

- name: Setup .NET
uses: actions/setup-dotnet@v6
with:
dotnet-version: "8.0.x"

- name: Resolve version
id: version
shell: pwsh
env:
INPUT_VERSION: ${{ github.event.inputs.version }}
run: |
$v = $env:INPUT_VERSION.TrimStart("v")
if ($v -notmatch '^\d+\.\d+\.\d+(-[0-9A-Za-z.\-]+)?$') { throw "Versão inválida: $v" }
"version=$v" >> $env:GITHUB_OUTPUT

- name: Run tests
shell: pwsh
run: dotnet test tests/ConsoleMode.Tests/ConsoleMode.Tests.csproj -c Release --nologo

- name: Install Inno Setup (if missing)
shell: pwsh
run: |
if (-not (Test-Path "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe")) { choco install innosetup -y --no-progress }

- name: Build portable + installer
shell: pwsh
run: .\build\Publish-ConsoleMode.ps1 -Runtime x64 -Target All -Version "${{ steps.version.outputs.version }}"

- name: Name the files Legacy
shell: pwsh
run: |
Rename-Item -LiteralPath "dist/ConsoleMode-Setup-x64.exe" -NewName "ConsoleMode-Legacy-Setup-x64.exe"
Rename-Item -LiteralPath "dist/ConsoleMode-Portable-x64.exe" -NewName "ConsoleMode-Legacy-Portable-x64.exe"

- name: Upload artifacts
uses: actions/upload-artifact@v7
with:
name: ConsoleMode-Legacy-${{ steps.version.outputs.version }}
path: |
dist/ConsoleMode-Legacy-Setup-x64.exe
dist/ConsoleMode-Legacy-Portable-x64.exe
if-no-files-found: error

build:
needs: legacy
# Without Legacy that job is skipped, and a skipped job would skip this one too.
if: ${{ !cancelled() && (needs.legacy.result == 'success' || needs.legacy.result == 'skipped') }}
runs-on: windows-latest
outputs:
version: ${{ steps.version.outputs.version }}
prerelease: ${{ steps.version.outputs.prerelease }}
publish: ${{ steps.version.outputs.publish }}
draft: ${{ steps.version.outputs.draft }}
steps:
- name: Checkout
uses: actions/checkout@v7
Expand All @@ -49,6 +129,7 @@ jobs:
REF: ${{ github.ref }}
INPUT_VERSION: ${{ github.event.inputs.version }}
INPUT_PUBLISH: ${{ github.event.inputs.publish }}
INPUT_DRAFT: ${{ github.event.inputs.draft }}
run: |
$v = if ($env:EVENT_NAME -eq "push") { $env:REF_NAME } else { $env:INPUT_VERSION }
$v = $v.TrimStart("v")
Expand All @@ -62,12 +143,16 @@ jobs:
"version=$v" >> $env:GITHUB_OUTPUT
"prerelease=$($v.Contains('-').ToString().ToLower())" >> $env:GITHUB_OUTPUT
"publish=$($publish.ToString().ToLower())" >> $env:GITHUB_OUTPUT
# A draft is only for a release made here: a pushed tag is public already.
$draft = $publish -and ($env:EVENT_NAME -ne "push") -and ($env:INPUT_DRAFT -eq "true")
"draft=$($draft.ToString().ToLower())" >> $env:GITHUB_OUTPUT

- name: Prepare release notes (English, a link to the Portuguese changelog, a summary per translated changelog)
if: steps.version.outputs.publish == 'true'
shell: pwsh
env:
VERSION: ${{ steps.version.outputs.version }}
LEGACY: ${{ github.event.inputs.legacy }}
run: |
function Get-Notes([string]$file) {
$changelog = Get-Content -LiteralPath $file -Raw -Encoding utf8
Expand Down Expand Up @@ -111,6 +196,19 @@ jobs:
# Single quotes: in double-quoted pwsh strings the backtick is an escape and the Markdown code spans vanish.
'- **Installer:** `ConsoleMode-Setup-x64.exe` — installs the app and offers shortcuts and starting with Windows.'
'- **Portable:** `ConsoleMode-Portable-x64.exe` — a single executable; keeps its data in the `ConsoleMode_Data` folder next to the file.'
)
if ($env:LEGACY) {
$releaseNotes += @(
""
"### Legacy"
""
"Prefer the old interface? **Console Mode Legacy** is 1.6.2 as it was, with the Desktop and Console interfaces. It opens with the settings you already have and keeps the ones only the current version uses, so you can switch back and forth. It is frozen: no new features, no fixes, and it never offers an update. To come back, install the current version over it."
""
'- **Legacy installer:** `ConsoleMode-Legacy-Setup-x64.exe`'
'- **Legacy portable:** `ConsoleMode-Legacy-Portable-x64.exe`'
)
}
$releaseNotes += @(
""
"---"
""
Expand Down Expand Up @@ -180,31 +278,55 @@ jobs:
dist/ConsoleMode-Portable-x64.exe
if-no-files-found: error

# The Legacy job's files of this run, next to the ones built here.
- name: Fetch the Legacy build
id: legacy
if: github.event_name == 'workflow_dispatch' && github.event.inputs.legacy != ''
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
run: |
gh run download $env:GITHUB_RUN_ID --repo $env:GITHUB_REPOSITORY --name "ConsoleMode-Legacy-$($env:VERSION)" --dir dist
foreach ($name in "ConsoleMode-Legacy-Setup-x64.exe", "ConsoleMode-Legacy-Portable-x64.exe") {
if (-not (Test-Path -LiteralPath (Join-Path "dist" $name))) { throw "The Legacy build did not bring $name" }
}
# A multi-line value for the release step below.
"files<<LIST" >> $env:GITHUB_OUTPUT
"dist/ConsoleMode-Legacy-Setup-x64.exe" >> $env:GITHUB_OUTPUT
"dist/ConsoleMode-Legacy-Portable-x64.exe" >> $env:GITHUB_OUTPUT
"LIST" >> $env:GITHUB_OUTPUT

- name: Publish GitHub release
if: steps.version.outputs.publish == 'true'
uses: softprops/action-gh-release@v3
with:
# Pushed tag: it already exists. Run by hand: it is created here, on the commit that was built.
# Pushed tag: it already exists. Run by hand: it is created here, on the commit that was built
# (for a draft, when the draft is published).
tag_name: v${{ steps.version.outputs.version }}
target_commitish: ${{ github.sha }}
name: Console Mode ${{ steps.version.outputs.version }}
prerelease: ${{ steps.version.outputs.prerelease }}
draft: ${{ steps.version.outputs.draft }}
fail_on_unmatched_files: true
generate_release_notes: false
append_body: false
body_path: release-notes.md
files: |
dist/ConsoleMode-Setup-x64.exe
dist/ConsoleMode-Portable-x64.exe
${{ steps.legacy.outputs.files }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# Opens the update PR on microsoft/winget-pkgs for stable releases (pre-releases are skipped).
# Opens the update PR on microsoft/winget-pkgs for stable releases (pre-releases and drafts are skipped;
# a draft goes to winget when it is published, through winget.yml).
# Off until the WINGET_TOKEN secret exists: a classic PAT with the public_repo scope, from the
# account that owns the lippdev/winget-pkgs fork.
winget:
needs: build
if: needs.build.outputs.publish == 'true' && needs.build.outputs.prerelease == 'false'
# "!cancelled()": the build job may have a skipped job (Legacy) before it.
if: ${{ !cancelled() && needs.build.result == 'success' && needs.build.outputs.publish == 'true' && needs.build.outputs.prerelease == 'false' && needs.build.outputs.draft != 'true' }}
runs-on: ubuntu-latest
env:
WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }}
Expand Down
37 changes: 37 additions & 0 deletions .github/workflows/winget.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Winget

# Sends a stable release to winget (an update PR on microsoft/winget-pkgs) when it is published by a person:
# a draft made by the Release workflow and published on GitHub, the usual way out of a test release.
# A release the Release workflow publishes right away never gets here (events caused by the workflow's own
# token don't start workflows): that one is sent by the "winget" job of release.yml.
# It can also be run by hand for a tag, if a submission has to be repeated.
# Off until the WINGET_TOKEN secret exists (see release.yml).
on:
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: "Tag of a published stable release (e.g. v1.7.0)."
required: true

permissions:
contents: read

jobs:
winget:
# Stable releases only: a pre-release tag has a hyphen.
if: ${{ !contains(github.event.release.tag_name || github.event.inputs.tag, '-') && github.event.release.prerelease != true }}
runs-on: ubuntu-latest
env:
WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }}
steps:
- name: Submit to winget-pkgs
if: env.WINGET_TOKEN != ''
uses: vedantmgoyal9/winget-releaser@v2
with:
identifier: lippdev.ConsoleMode
release-tag: ${{ github.event.release.tag_name || github.event.inputs.tag }}
installers-regex: 'ConsoleMode-Setup-x64\.exe$'
fork-user: lippdev
token: ${{ env.WINGET_TOKEN }}
2 changes: 1 addition & 1 deletion docs/GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ Requires [Visual Studio 2022](https://visualstudio.microsoft.com/) with the **Wi

Output: `dist\ConsoleMode-Portable-x64.exe` and `dist\ConsoleMode-Setup-x64.exe` (the installer needs [Inno Setup 6](https://jrsoftware.org/isinfo.php): `winget install JRSoftware.InnoSetup`). Open `ConsoleMode.sln` to debug.

To release, merge the release PR into `main`, then run Actions → **Release** → Run workflow on `main` with the version (like `1.4.0`, or `1.4.0-beta.2` for a pre-release) and **publish** ticked: the workflow creates the tag and the GitHub release, builds both files and publishes them, and the app picks them up as an update. Without "publish" it only builds and uploads the files as an artifact. Pushing a `v*` tag still works and does the same.
To release, merge the release PR into `main`, then run Actions → **Release** → Run workflow on `main` with the version (like `1.4.0`, or `1.4.0-beta.2` for a pre-release) and **publish** ticked: the workflow creates the tag and the GitHub release, builds both files and publishes them, and the app picks them up as an update. Without "publish" it only builds and uploads the files as an artifact. Pushing a `v*` tag still works and does the same. With **draft** ticked too, the release is created as a draft: only the repository's maintainers see it, the app offers nothing, nothing goes to winget and the tag isn't created yet, so the files can be tried first; publishing the draft on GitHub makes it a normal release (and sends a stable one to winget). **legacy** takes a branch (`release/1.7-legacy`) to build and attach to the same release as `ConsoleMode-Legacy-*.exe`: Console Mode 1.6.2's interfaces, frozen, which the update check never offers.

The previous PowerShell + WPF implementation (1.2 and earlier) lives on the [`legacy`](https://github.com/lippdev/consolemode/tree/legacy) branch and is not used by the WinUI app.

2 changes: 1 addition & 1 deletion docs/GUIDE.pt-BR.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,6 @@ Precisa do [Visual Studio 2022](https://visualstudio.microsoft.com/) com a workl

Saída: `dist\ConsoleMode-Portable-x64.exe` e `dist\ConsoleMode-Setup-x64.exe` (o instalador precisa do [Inno Setup 6](https://jrsoftware.org/isinfo.php): `winget install JRSoftware.InnoSetup`). Abra `ConsoleMode.sln` para depurar.

Para lançar uma versão, faça o merge do PR de release na `main` e rode Actions → **Release** → Run workflow na `main` com a versão (como `1.4.0`, ou `1.4.0-beta.2` para pré-release) e **publish** marcado: o workflow cria a tag e a release no GitHub, gera os dois arquivos e os publica, e o app oferece a atualização. Sem "publish" ele só gera e guarda os arquivos como artefato. Fazer push de uma tag `v*` continua funcionando e faz o mesmo.
Para lançar uma versão, faça o merge do PR de release na `main` e rode Actions → **Release** → Run workflow na `main` com a versão (como `1.4.0`, ou `1.4.0-beta.2` para pré-release) e **publish** marcado: o workflow cria a tag e a release no GitHub, gera os dois arquivos e os publica, e o app oferece a atualização. Sem "publish" ele só gera e guarda os arquivos como artefato. Fazer push de uma tag `v*` continua funcionando e faz o mesmo. Com **draft** marcado também, a release é criada como rascunho: só os mantenedores do repositório a veem, o app não oferece nada, nada vai para o winget e a tag ainda não é criada, para dar tempo de experimentar os arquivos; publicar o rascunho no GitHub faz dela uma release normal (e manda uma estável para o winget). **legacy** recebe uma branch (`release/1.7-legacy`) para gerar e anexar na mesma release como `ConsoleMode-Legacy-*.exe`: as interfaces do Console Mode 1.6.2, congeladas, que a verificação de atualizações nunca oferece.

A implementação antiga em PowerShell + WPF (1.2 e anteriores) fica na branch [`legacy`](https://github.com/lippdev/consolemode/tree/legacy) e não é usada pelo app WinUI.
Loading