mirror of
https://github.com/zealdocs/zeal.git
synced 2026-08-29 08:34:50 +08:00
Compare commits
16 Commits
v0.9.0
...
0dfb36c837
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dfb36c837 | |||
| ae4086f7a0 | |||
| 25ad56c62e | |||
| 25c0e915a7 | |||
| 366d6f47c3 | |||
| fc8da85fb1 | |||
| a6f03e9547 | |||
| ac6eca8a9b | |||
| a716f6c170 | |||
| 7a881b6921 | |||
| e6a3eb7afc | |||
| 530fa44395 | |||
| c7bcf3d4b4 | |||
| f854fcf8d7 | |||
| cd12f8dcf5 | |||
| 5edfac529b |
@@ -163,6 +163,11 @@ jobs:
|
||||
if: matrix.config.publishArtifacts
|
||||
run: cmake --build --preset ${{ matrix.config.buildPreset }} --target package
|
||||
|
||||
- name: Test MSI
|
||||
if: matrix.config.publishArtifacts && matrix.config.configurePreset == 'release'
|
||||
shell: pwsh
|
||||
run: pwsh -NoProfile -File pkg/wix/tools/test-msi.ps1 -Install
|
||||
|
||||
- name: Upload ZIP Artifacts
|
||||
if: matrix.config.publishArtifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
|
||||
@@ -38,13 +38,17 @@ jobs:
|
||||
next_version="${major}.${minor}.${next_patch}"
|
||||
|
||||
sed -i "/^project(/,/^)/ s/${version}/${next_version}/" CMakeLists.txt
|
||||
|
||||
# The nightly recipe reads this version via {debupstream}.
|
||||
sed -i "1s/(1:[^-]*-/(1:${next_version}-/" pkg/ppa/debian/changelog
|
||||
|
||||
echo "NEXT_VERSION=${next_version}" >> $GITHUB_ENV
|
||||
|
||||
- name: Commit & Push
|
||||
run: |
|
||||
git config user.name "zealdocs-ci[bot]"
|
||||
git config user.email "273095467+zealdocs-ci[bot]@users.noreply.github.com"
|
||||
git add CMakeLists.txt
|
||||
git add CMakeLists.txt pkg/ppa/debian/changelog
|
||||
git diff --staged --quiet && echo "::error::Version bump failed, no changes detected." && exit 1
|
||||
git commit -m "chore: bump version to ${{ env.NEXT_VERSION }}"
|
||||
git push
|
||||
|
||||
@@ -19,7 +19,7 @@ env:
|
||||
# Ubuntu series as <codename>:<version> pairs. 24.04 (noble) is the floor; 22.04's
|
||||
# Qt 6.2 is too old. <version> forms the ~ubuntu<version> suffix, <codename> is the
|
||||
# changelog distribution. Launchpad rejects EOL or unknown series.
|
||||
SERIES: "noble:24.04 questing:25.10 resolute:26.04"
|
||||
SERIES: "noble:24.04 resolute:26.04"
|
||||
PPA: "ppa:zealdocs/ppa"
|
||||
|
||||
jobs:
|
||||
@@ -166,7 +166,9 @@ jobs:
|
||||
# Guard so one rejected series doesn't abort the rest (the if-context
|
||||
# suspends set -e). Flip `first` only on success, so the orig tarball
|
||||
# still ships with the next series if this upload failed.
|
||||
if ( cd "$work" && debuild --no-lintian -S "$tarball_opt" -k"$GPG_KEYID" -p"$HOME/.gpg-sign" ) \
|
||||
# -d skips the build-dependency check: nothing is compiled here, and
|
||||
# the dependencies are resolved on the Launchpad builders instead.
|
||||
if ( cd "$work" && debuild --no-lintian -d -S "$tarball_opt" -k"$GPG_KEYID" -p"$HOME/.gpg-sign" ) \
|
||||
&& dput "$PPA" "$src_root/zeal_${file_ver}_source.changes"; then
|
||||
first=false
|
||||
else
|
||||
|
||||
@@ -16,7 +16,7 @@ on:
|
||||
- beta
|
||||
- edge
|
||||
schedule:
|
||||
- cron: '0 0 * * 2'
|
||||
- cron: '2 4 * * *'
|
||||
|
||||
permissions: {}
|
||||
|
||||
|
||||
+9
-3
@@ -9,21 +9,27 @@ setup_homebrew()
|
||||
# CMake options.
|
||||
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
|
||||
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
|
||||
set(CMAKE_ERROR_DEPRECATED TRUE)
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
if(POLICY CMP0218)
|
||||
cmake_policy(SET CMP0218 NEW)
|
||||
cmake_diagnostic(SET CMD_DEPRECATED FATAL_ERROR)
|
||||
else()
|
||||
set(CMAKE_ERROR_DEPRECATED TRUE)
|
||||
endif()
|
||||
|
||||
# VERSION is the next development version, bumped automatically after each release.
|
||||
# ZEAL_RELEASE_VERSION is the last released version, updated by `just release-prepare`.
|
||||
# When both match, the build is treated as a release; otherwise it's a dev build.
|
||||
# The `# x-version` marker on each version line acts as a sed anchor for the bump.
|
||||
project(Zeal
|
||||
VERSION 0.9.0 # x-version
|
||||
VERSION 0.9.2 # x-version
|
||||
DESCRIPTION "A simple documentation browser."
|
||||
HOMEPAGE_URL "https://zealdocs.org"
|
||||
LANGUAGES CXX
|
||||
)
|
||||
|
||||
set(ZEAL_RELEASE_VERSION "0.9.0") # x-version
|
||||
set(ZEAL_RELEASE_VERSION "0.9.1") # x-version
|
||||
|
||||
include(ZealHelpers)
|
||||
|
||||
|
||||
@@ -49,6 +49,14 @@
|
||||
<id>zeal.desktop</id>
|
||||
</provides>
|
||||
<releases>@ZEAL_APPSTREAM_DEV_RELEASE@
|
||||
<release date="2026-07-28" version="0.9.1" type="stable">
|
||||
<description>
|
||||
<ul>
|
||||
<li>Maintenance release with no changes for Linux users</li>
|
||||
</ul>
|
||||
</description>
|
||||
<url>https://github.com/zealdocs/zeal/releases/tag/v0.9.1</url>
|
||||
</release>
|
||||
<release date="2026-07-28" version="0.9.0" type="stable">
|
||||
<description>
|
||||
<ul>
|
||||
|
||||
@@ -98,17 +98,7 @@ release-prepare version:
|
||||
# Maintainer use only.
|
||||
[group('release')]
|
||||
release-push version remote="origin":
|
||||
git add assets/freedesktop/org.zealdocs.zeal.appdata.xml.in CMakeLists.txt
|
||||
git diff --staged --quiet || git commit -m "chore: release v{{version}}"
|
||||
# Annotated: `git describe` without `--tags` ignores lightweight tags, and
|
||||
# the AUR zeal-git package derives its version that way.
|
||||
git rev-parse -q --verify refs/tags/v{{version}} > /dev/null || git tag -a v{{version}} -m "v{{version}}"
|
||||
git push {{remote}} HEAD
|
||||
gh release create v{{version}} --draft --notes-file build/release-notes.md \
|
||||
--repo "$(git remote get-url {{remote}} | sed -E 's|^.*github\.com[:/]||; s|\.git$||')"
|
||||
git push {{remote}} v{{version}}
|
||||
@echo "Pushed v{{version}} with draft release. CI will upload artifacts."
|
||||
@echo "Approve the 'release' environment to let the Windows jobs run."
|
||||
bash tools/release-push.sh {{version}} {{remote}}
|
||||
|
||||
# Delete the draft release, the remote tag, and the local tag for a version,
|
||||
# undoing `just release-push` so it can be run again. Refuses to delete a
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
zeal (1:0.8.2-0ubuntu1) UNRELEASED; urgency=medium
|
||||
zeal (1:0.9.2-0ubuntu1) UNRELEASED; urgency=medium
|
||||
|
||||
* Placeholder entry. The real version and target series are set at upload
|
||||
time by debian/rules consumers: the release workflow rewrites this with
|
||||
`dch` per series, and the Launchpad nightly recipe derives the version
|
||||
from its `deb-version` template. See pkg/ppa/README.md.
|
||||
* Placeholder entry, except for the version above. Releases rewrite this file
|
||||
with `dch` per series in publish-ppa.yaml, but the Launchpad nightly recipe
|
||||
reads that version through `{debupstream}` and appends `-0~{revtime}`. It
|
||||
must name the next, unreleased version, so a nightly sorts above the last
|
||||
release and below the next one. Keep it in step with CMakeLists.txt;
|
||||
chore-version-bump.yaml does that on release. See pkg/ppa/README.md.
|
||||
|
||||
-- Zeal Release <release@zealdocs.org> Thu, 01 May 2025 00:00:00 +0000
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." />
|
||||
|
||||
<Launch Condition="VersionNT64" Message="This package can only be installed on 64-bit versions of Windows." />
|
||||
<!-- Qt supports Windows 10 version 1809 (build 17763) and later. Repair and removal of an
|
||||
existing installation remain possible on older builds, while an upgrade is refused
|
||||
there, since the newer version would not start. -->
|
||||
<Launch Condition="Installed OR WindowsBuild >= 17763" Message="[ProductName] requires Windows 10 version 1809 or later." />
|
||||
|
||||
<Property Id="WIXUI_INSTALLDIR" Value="INSTALL_ROOT" />
|
||||
|
||||
|
||||
@@ -104,7 +104,6 @@ Docset::Docset(QString path)
|
||||
|
||||
if (plist.hasError()) {
|
||||
qCWarning(log, "Failed to parse 'Info.plist' for docset at '%s'.", qPrintable(m_path));
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_name.isEmpty()) {
|
||||
|
||||
@@ -79,7 +79,7 @@ Copyright &copy; Oleg Shparber and other contributors, 2013-2026.
|
||||
<br>
|
||||
<a href="https://zealdocs.org">zealdocs.org</a>
|
||||
<br>
|
||||
<a href="ircs://irc.libera.chat:6697/zealdocs">#zealdocs</a> on <a href="https://libera.chat">Libera Chat</a>
|
||||
<a href="https://go.zealdocs.org/l/contact">Get in touch</a>
|
||||
<br><br>
|
||||
Zeal is an open source software available under the terms of the General Public License version 3 (<a href="https://www.gnu.org/copyleft/gpl.html">GPLv3</a>) or later.
|
||||
<br><br>
|
||||
|
||||
@@ -22,7 +22,8 @@ bool Plist::read(const QString &fileName)
|
||||
return false;
|
||||
}
|
||||
|
||||
QXmlStreamReader xml(&file);
|
||||
// Some docsets ship an Info.plist with whitespace before the XML declaration.
|
||||
QXmlStreamReader xml(file.readAll().trimmed());
|
||||
|
||||
while (!xml.atEnd()) {
|
||||
const QXmlStreamReader::TokenType token = xml.readNext();
|
||||
|
||||
@@ -6,6 +6,12 @@ target_link_libraries(fuzzy_test PRIVATE Util Qt6::Test)
|
||||
|
||||
zeal_add_test(fuzzy_test)
|
||||
|
||||
# Property list tests
|
||||
add_executable(plist_test plist_test.cpp)
|
||||
target_link_libraries(plist_test PRIVATE Util Qt6::Test)
|
||||
|
||||
zeal_add_test(plist_test)
|
||||
|
||||
# SQLite Statement tests
|
||||
add_executable(statement_test statement_test.cpp)
|
||||
target_link_libraries(statement_test PRIVATE Util Qt6::Test)
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright (C) Oleg Shparber, et al. <https://zealdocs.org>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "../plist.h"
|
||||
|
||||
#include <QtTest>
|
||||
|
||||
using namespace Zeal::Util;
|
||||
|
||||
class PlistTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
|
||||
void testReadsKeys();
|
||||
void testLeadingNewline();
|
||||
void testLeadingIndentation();
|
||||
void testByteOrderMark();
|
||||
void testMalformedContent();
|
||||
void testMissingFile();
|
||||
|
||||
private:
|
||||
QString writePlist(const QByteArray &data);
|
||||
|
||||
QTemporaryDir m_dir;
|
||||
int m_counter = 0;
|
||||
};
|
||||
|
||||
namespace {
|
||||
const QByteArray Body = QByteArrayLiteral("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
|
||||
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\""
|
||||
" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
|
||||
"<plist version=\"1.0\">\n"
|
||||
" <dict>\n"
|
||||
" <key>CFBundleName</key>\n"
|
||||
" <string>Android KTX</string>\n"
|
||||
" <key>isDashDocset</key>\n"
|
||||
" <true/>\n"
|
||||
" <key>isJavaScriptEnabled</key>\n"
|
||||
" <false/>\n"
|
||||
" </dict>\n"
|
||||
"</plist>\n");
|
||||
} // namespace
|
||||
|
||||
QString PlistTest::writePlist(const QByteArray &data)
|
||||
{
|
||||
const QString path = m_dir.filePath(QStringLiteral("Info%1.plist").arg(++m_counter));
|
||||
QFile file(path);
|
||||
if (!file.open(QIODevice::WriteOnly) || file.write(data) != data.size()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void PlistTest::initTestCase()
|
||||
{
|
||||
QVERIFY(m_dir.isValid());
|
||||
}
|
||||
|
||||
void PlistTest::testReadsKeys()
|
||||
{
|
||||
Plist plist;
|
||||
QVERIFY(plist.read(writePlist(Body)));
|
||||
QVERIFY(!plist.hasError());
|
||||
QCOMPARE(plist.value(QStringLiteral("CFBundleName")), QVariant(QStringLiteral("Android KTX")));
|
||||
QCOMPARE(plist.value(QStringLiteral("isDashDocset")), QVariant(true));
|
||||
QCOMPARE(plist.value(QStringLiteral("isJavaScriptEnabled")), QVariant(false));
|
||||
}
|
||||
|
||||
// See: https://github.com/zealdocs/zeal/issues/1949
|
||||
void PlistTest::testLeadingNewline()
|
||||
{
|
||||
Plist plist;
|
||||
QVERIFY(plist.read(writePlist(QByteArrayLiteral("\n") + Body)));
|
||||
QVERIFY(!plist.hasError());
|
||||
QCOMPARE(plist[QStringLiteral("CFBundleName")].toString(), QStringLiteral("Android KTX"));
|
||||
}
|
||||
|
||||
void PlistTest::testLeadingIndentation()
|
||||
{
|
||||
Plist plist;
|
||||
QVERIFY(plist.read(writePlist(QByteArrayLiteral("\n ") + Body)));
|
||||
QVERIFY(!plist.hasError());
|
||||
QCOMPARE(plist[QStringLiteral("CFBundleName")].toString(), QStringLiteral("Android KTX"));
|
||||
}
|
||||
|
||||
void PlistTest::testByteOrderMark()
|
||||
{
|
||||
Plist plist;
|
||||
QVERIFY(plist.read(writePlist(QByteArrayLiteral("\xEF\xBB\xBF") + Body)));
|
||||
QVERIFY(!plist.hasError());
|
||||
QCOMPARE(plist[QStringLiteral("CFBundleName")].toString(), QStringLiteral("Android KTX"));
|
||||
}
|
||||
|
||||
void PlistTest::testMalformedContent()
|
||||
{
|
||||
const QString path = writePlist(QByteArrayLiteral("<plist><dict><key>CFBundleName</key>"));
|
||||
QVERIFY(!path.isEmpty());
|
||||
|
||||
Plist plist;
|
||||
QVERIFY(!plist.read(path));
|
||||
QVERIFY(plist.hasError());
|
||||
}
|
||||
|
||||
void PlistTest::testMissingFile()
|
||||
{
|
||||
Plist plist;
|
||||
QVERIFY(!plist.read(m_dir.filePath(QStringLiteral("Missing.plist"))));
|
||||
QVERIFY(plist.hasError());
|
||||
}
|
||||
|
||||
QTEST_GUILESS_MAIN(PlistTest)
|
||||
#include "plist_test.moc"
|
||||
@@ -75,20 +75,38 @@ would notice and care about. There is no target count: include a change \
|
||||
only if it earns its place, and leave out cosmetic trivia, internal \
|
||||
refactors, build/CI/dependency commits, and Windows-only or macOS-only \
|
||||
changes. If you cannot tell a change's user-visible effect from its diff, \
|
||||
omit it. Write each as one <li>...</li> bullet that starts with Added, \
|
||||
omit it. Write each as one plain-text line that starts with Added, \
|
||||
Changed, Removed, Deprecated, or Fixed, grouped in that order (Added first, \
|
||||
Fixed last) and most significant first within each group. Keep each bullet \
|
||||
Fixed last) and most significant first within each group. Keep each line \
|
||||
concrete and specific about what changed, in plain language a non-developer \
|
||||
understands; a short clause on why it helps is welcome. No trailing period. \
|
||||
Avoid AI cliches (em-dashes, 'delve into', 'leverage', 'robust', 'ensure', \
|
||||
'seamless', 'comprehensive'). Output the <li> lines only: no preamble, \
|
||||
commentary, or wrapping <ul>." \
|
||||
'seamless', 'comprehensive'). Output the lines only: no markup, numbering, \
|
||||
bullet characters, preamble, or commentary. If nothing qualifies, output \
|
||||
exactly one line reading: Maintenance release with no changes for Linux \
|
||||
users" \
|
||||
--allowedTools "Bash(git log:*) Bash(git show:*) Bash(git diff:*)" \
|
||||
< /dev/null \
|
||||
> build/appdata-bullets.txt
|
||||
|
||||
today=$(date -u +%Y-%m-%d)
|
||||
indented=$(sed 's/^[[:space:]]*//; s/^/ /' build/appdata-bullets.txt)
|
||||
|
||||
# Bullets arrive as plain text, one per line. Wrapping them here, rather than
|
||||
# asking for markup, keeps stray commentary from producing invalid XML.
|
||||
indented=$(while read -r line; do
|
||||
[ -n "$line" ] || continue
|
||||
# Ampersands are escaped as \& because bash 5.2+ reads a bare & in the
|
||||
# replacement as the matched text.
|
||||
line=${line//&/\&}
|
||||
line=${line//</\<}
|
||||
line=${line//>/\>}
|
||||
printf ' <li>%s</li>\n' "$line"
|
||||
done < build/appdata-bullets.txt)
|
||||
|
||||
if [ -z "$indented" ]; then
|
||||
echo "build/appdata-bullets.txt produced no bullets; aborting." >&2
|
||||
exit 1
|
||||
fi
|
||||
cat > build/release-block.xml <<EOF
|
||||
<release date="${today}" version="${VERSION}" type="stable">
|
||||
<description>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# release-push.sh - Commit, tag, and push a prepared release.
|
||||
#
|
||||
# SPDX-FileCopyrightText: Oleg Shparber, et al. <https://zealdocs.org>
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Commits the appdata and version bump left by release-prepare.sh, pushes the
|
||||
# branch, creates the draft GitHub release from the generated notes, then tags
|
||||
# and pushes the tag, which starts the build CI. The commit and tag steps are
|
||||
# skipped if already done, so the same version can go to a fork first and then
|
||||
# be promoted to upstream.
|
||||
#
|
||||
# Usage: tools/release-push.sh <version> [remote]
|
||||
#
|
||||
|
||||
set -euo pipefail
|
||||
trap 'echo "ERROR: failed at line ${LINENO}: ${BASH_COMMAND}" >&2' ERR
|
||||
|
||||
if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
|
||||
echo "Usage: $0 <version> [remote]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
VERSION="$1"
|
||||
REMOTE="${2:-origin}"
|
||||
TAG="v${VERSION}"
|
||||
|
||||
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Invalid version: '${VERSION}'. Expected major.minor.patch (e.g. 0.9.0)." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
repo=$(git remote get-url "$REMOTE" | sed -E 's|^.*github\.com[:/]||; s|\.git$||')
|
||||
|
||||
git add assets/freedesktop/org.zealdocs.zeal.appdata.xml.in CMakeLists.txt
|
||||
if git diff --staged --quiet; then
|
||||
echo "Nothing to commit; ${TAG} content is already committed."
|
||||
else
|
||||
git commit -m "chore: release ${TAG}"
|
||||
fi
|
||||
|
||||
# Annotated: `git describe` without `--tags` ignores lightweight tags, and the
|
||||
# AUR zeal-git package derives its version that way.
|
||||
if git rev-parse -q --verify "refs/tags/${TAG}" > /dev/null; then
|
||||
echo "Tag ${TAG} already exists; reusing it."
|
||||
else
|
||||
git tag -a "$TAG" -m "$TAG"
|
||||
fi
|
||||
|
||||
git push "$REMOTE" HEAD
|
||||
|
||||
# Created before the tag is pushed, so the draft is in place when CI starts.
|
||||
gh release create "$TAG" --draft --notes-file build/release-notes.md --repo "$repo"
|
||||
|
||||
git push "$REMOTE" "$TAG"
|
||||
|
||||
echo "Pushed ${TAG} to ${repo}. CI will build, upload, and publish."
|
||||
Reference in New Issue
Block a user