ci: add versioned release pipeline
This commit is contained in:
@@ -0,0 +1,52 @@
|
|||||||
|
name: ci
|
||||||
|
|
||||||
|
"on":
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
pull_request:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-linux-amd64:
|
||||||
|
runs-on: [self-hosted, linux, arch, homelab]
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configure release build
|
||||||
|
shell: bash
|
||||||
|
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: cmake --build build --parallel
|
||||||
|
|
||||||
|
- name: Smoke test GUI
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set +e
|
||||||
|
QT_QPA_PLATFORM=offscreen timeout 3s ./build/searchmyfiles
|
||||||
|
status="$?"
|
||||||
|
test "$status" = 0 || test "$status" = 124
|
||||||
|
|
||||||
|
- name: Upload Linux binary
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: folderscope-linux-amd64
|
||||||
|
path: build/searchmyfiles
|
||||||
|
|
||||||
|
lint-yaml:
|
||||||
|
runs-on: [self-hosted, linux, arch, homelab]
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Lint workflow files
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
docker run --rm \
|
||||||
|
-v "$PWD:/work" \
|
||||||
|
-w /work \
|
||||||
|
cytopia/yamllint:latest \
|
||||||
|
-c .yamllint .
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
name: release
|
||||||
|
|
||||||
|
"on":
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v[0-9]*.[0-9]*.[0-9]*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
verify:
|
||||||
|
runs-on: [self-hosted, linux, arch, homelab]
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Verify tag matches VERSION
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
tag="${GITHUB_REF##*/}"
|
||||||
|
test "${tag#v}" = "$(tr -d '[:space:]' < VERSION)"
|
||||||
|
|
||||||
|
- name: Configure release build
|
||||||
|
shell: bash
|
||||||
|
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: cmake --build build --parallel
|
||||||
|
|
||||||
|
- name: Smoke test GUI
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set +e
|
||||||
|
QT_QPA_PLATFORM=offscreen timeout 3s ./build/searchmyfiles
|
||||||
|
status="$?"
|
||||||
|
test "$status" = 0 || test "$status" = 124
|
||||||
|
|
||||||
|
- name: Lint YAML
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
docker run --rm \
|
||||||
|
-v "$PWD:/work" \
|
||||||
|
-w /work \
|
||||||
|
cytopia/yamllint:latest \
|
||||||
|
-c .yamllint .
|
||||||
|
|
||||||
|
linux-amd64:
|
||||||
|
needs: verify
|
||||||
|
runs-on: [self-hosted, linux, arch, homelab]
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Configure release build
|
||||||
|
shell: bash
|
||||||
|
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
shell: bash
|
||||||
|
run: cmake --build build --parallel
|
||||||
|
|
||||||
|
- name: Package release
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
tag="${GITHUB_REF##*/}"
|
||||||
|
version="${tag#v}"
|
||||||
|
package="folderscope-${version}-linux-amd64"
|
||||||
|
rm -rf dist package
|
||||||
|
cmake --install build --prefix "$PWD/package/usr"
|
||||||
|
mkdir -p "package/${package}"
|
||||||
|
mv package/usr "package/${package}/"
|
||||||
|
cp README.md CHANGELOG.md VERSION "package/${package}/"
|
||||||
|
mkdir -p dist
|
||||||
|
tar -C package -czf "dist/${package}.tar.gz" "${package}"
|
||||||
|
sha256sum "dist/${package}.tar.gz" > "dist/${package}.tar.gz.sha256"
|
||||||
|
|
||||||
|
- name: Create Gitea release
|
||||||
|
id: release
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
tag="${GITHUB_REF##*/}"
|
||||||
|
release_url="https://gitea.forust.xyz/api/v1/repos/forust/folderscope/releases"
|
||||||
|
existing="$(curl -fsS \
|
||||||
|
"${release_url}/tags/${tag}" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}")" || existing='{}'
|
||||||
|
release_id="$(printf '%s' "$existing" | jq -r '.id // empty')"
|
||||||
|
|
||||||
|
if [ -z "$release_id" ]; then
|
||||||
|
payload="$(jq -n \
|
||||||
|
--arg tag "${tag}" \
|
||||||
|
--arg commit "${GITHUB_SHA}" \
|
||||||
|
--arg name "FolderScope ${tag}" \
|
||||||
|
--arg body "Release ${tag}. See CHANGELOG.md for notable changes." \
|
||||||
|
'{tag_name: $tag, target_commitish: $commit, name: $name, body: $body, draft: false, prerelease: false}')"
|
||||||
|
response="$(curl -fsS \
|
||||||
|
-X POST "${release_url}" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$payload")"
|
||||||
|
release_id="$(printf '%s' "$response" | jq -r '.id')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
test -n "$release_id" && test "$release_id" != "null"
|
||||||
|
echo "release_id=${release_id}" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
|
- name: Upload Gitea release assets
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
release_url="https://gitea.forust.xyz/api/v1/repos/forust/folderscope/releases"
|
||||||
|
release_id="${{ steps.release.outputs.release_id }}"
|
||||||
|
for asset in dist/*; do
|
||||||
|
name="$(basename "$asset")"
|
||||||
|
release="$(curl -fsS \
|
||||||
|
"${release_url}/${release_id}" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}")"
|
||||||
|
asset_id="$(printf '%s' "$release" | jq -r --arg name "$name" \
|
||||||
|
'.assets[]? | select(.name == $name) | .id' | head -n 1)"
|
||||||
|
if [ -n "$asset_id" ]; then
|
||||||
|
curl -fsS \
|
||||||
|
-X DELETE "${release_url}/${release_id}/assets/${asset_id}" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}"
|
||||||
|
fi
|
||||||
|
encoded="$(printf '%s' "$name" | jq -sRr @uri)"
|
||||||
|
curl -fsS \
|
||||||
|
-X POST "${release_url}/${release_id}/assets?name=${encoded}" \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-F "attachment=@${asset}"
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Upload workflow artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: folderscope-linux-amd64
|
||||||
|
path: dist/*
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
extends: default
|
||||||
|
|
||||||
|
rules:
|
||||||
|
comments:
|
||||||
|
min-spaces-from-content: 1
|
||||||
|
comments-indentation: false
|
||||||
|
document-start: disable
|
||||||
|
line-length:
|
||||||
|
max: 140
|
||||||
|
braces:
|
||||||
|
min-spaces-inside: 0
|
||||||
|
max-spaces-inside: 1
|
||||||
|
brackets:
|
||||||
|
min-spaces-inside: 0
|
||||||
|
max-spaces-inside: 1
|
||||||
|
indentation:
|
||||||
|
spaces: 2
|
||||||
|
indent-sequences: consistent
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to FolderScope are documented here.
|
||||||
|
|
||||||
|
The project uses [Semantic Versioning](https://semver.org/). Release tags are
|
||||||
|
formatted as `vMAJOR.MINOR.PATCH`.
|
||||||
|
|
||||||
|
## [0.2.0] - 2026-07-25
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Initial Linux desktop release with C++20 and Qt 6.
|
||||||
|
- Advanced file search, content search, duplicate detection, summaries, and
|
||||||
|
CSV/TXT/HTML/XML/JSON export.
|
||||||
|
- Configurable columns, persistent UI settings, context actions, and progress
|
||||||
|
reporting.
|
||||||
|
|
||||||
|
[0.2.0]: https://gitea.forust.xyz/forust/folderscope/releases/tag/v0.2.0
|
||||||
+9
-1
@@ -1,5 +1,12 @@
|
|||||||
cmake_minimum_required(VERSION 3.21)
|
cmake_minimum_required(VERSION 3.21)
|
||||||
project(searchmyfiles VERSION 0.2.0 LANGUAGES CXX)
|
|
||||||
|
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" FOLDERSCOPE_VERSION)
|
||||||
|
string(STRIP "${FOLDERSCOPE_VERSION}" FOLDERSCOPE_VERSION)
|
||||||
|
if (NOT FOLDERSCOPE_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+$")
|
||||||
|
message(FATAL_ERROR "VERSION must use MAJOR.MINOR.PATCH: ${FOLDERSCOPE_VERSION}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
project(folderscope VERSION ${FOLDERSCOPE_VERSION} LANGUAGES CXX)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
@@ -13,6 +20,7 @@ qt_add_executable(searchmyfiles
|
|||||||
|
|
||||||
target_link_libraries(searchmyfiles PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::DBus)
|
target_link_libraries(searchmyfiles PRIVATE Qt6::Widgets Qt6::Concurrent Qt6::DBus)
|
||||||
target_compile_options(searchmyfiles PRIVATE -Wall -Wextra -Wpedantic)
|
target_compile_options(searchmyfiles PRIVATE -Wall -Wextra -Wpedantic)
|
||||||
|
target_compile_definitions(searchmyfiles PRIVATE FOLDERSCOPE_VERSION="${PROJECT_VERSION}")
|
||||||
|
|
||||||
install(TARGETS searchmyfiles RUNTIME DESTINATION bin)
|
install(TARGETS searchmyfiles RUNTIME DESTINATION bin)
|
||||||
install(FILES packaging/searchmyfiles.desktop
|
install(FILES packaging/searchmyfiles.desktop
|
||||||
|
|||||||
Executable
+34
@@ -0,0 +1,34 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ $# -ne 1 || ! "$1" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||||
|
echo "Usage: $0 MAJOR.MINOR.PATCH" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
version="$1"
|
||||||
|
tag="v${version}"
|
||||||
|
|
||||||
|
if ! git diff --quiet || ! git diff --cached --quiet; then
|
||||||
|
echo "Refusing to release with uncommitted changes." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if git rev-parse -q --verify "refs/tags/${tag}" >/dev/null; then
|
||||||
|
echo "Tag ${tag} already exists." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! grep -q "^## \[${version}\]" CHANGELOG.md; then
|
||||||
|
echo "Add a ## [${version}] section to CHANGELOG.md first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
current_version="$(tr -d '[:space:]' < VERSION)"
|
||||||
|
if [[ "$current_version" != "$version" ]]; then
|
||||||
|
printf '%s\n' "$version" > VERSION
|
||||||
|
git add VERSION
|
||||||
|
git commit -m "chore: release ${tag}"
|
||||||
|
fi
|
||||||
|
git tag -a "$tag" -m "Release ${tag}"
|
||||||
|
|
||||||
|
echo "Created ${tag}. Publish it with:"
|
||||||
|
echo " git push origin main --follow-tags"
|
||||||
+2
-1
@@ -1231,7 +1231,8 @@ public:
|
|||||||
|
|
||||||
menuBar()->addMenu(tr("&Help"))->addAction(tr("About"), this, [this] {
|
menuBar()->addMenu(tr("&Help"))->addAction(tr("About"), this, [this] {
|
||||||
QMessageBox::about(this, tr("About"),
|
QMessageBox::about(this, tr("About"),
|
||||||
tr("SearchMyFiles for Linux\n\nFast unindexed file search.\nC++20 + Qt 6."));
|
tr("FolderScope %1\n\nFast unindexed file search.\nC++20 + Qt 6.")
|
||||||
|
.arg(QStringLiteral(FOLDERSCOPE_VERSION)));
|
||||||
});
|
});
|
||||||
|
|
||||||
progress_ = new QProgressBar;
|
progress_ = new QProgressBar;
|
||||||
|
|||||||
Reference in New Issue
Block a user