Compare commits

...
9 Commits
Author SHA1 Message Date
github-actions[bot] e2bf75b774 Bump versions for v13.10 2026-11-13 04:11:48 +00:00
Lauri Ojansivu d6c7dbcde2 Prepare v13.10 release 2026-11-13 06:10:46 +02:00
Lauri Ojansivu 8b44646314 CHANGELOG: every snapcraft install attempt is bounded, and snap-auth-check has room for all five.
Thanks to xet7 !
2026-11-13 06:06:16 +02:00
Lauri Ojansivu 560ff74a79 Release: every snapcraft install attempt is bounded, and snap-auth-check has room for all five.
In the v13.09 release the Snap Store failed snap-auth-check's first two
install attempts and then let the third hang with no output, until the job's
10-minute timeout cancelled it - the retry added for v13.07 never got its
remaining turns. Each `snap install snapcraft` in release-all.yml now runs
under `timeout 180`, and an attempt cut short is aborted (`snap abort
--last=install`) so the next one does not meet snapd's change still in
progress. snap-auth-check's job timeout is 25 minutes, enough for five
attempts 30 seconds apart and the whoami after them.

tests/snapAuthPreflight.test.cjs requires every install in the workflows to
be bounded and followed by the abort, and fails when snap-auth-check's job
timeout cannot hold all five attempts.

Thanks to xet7 !
2026-11-13 06:05:56 +02:00
github-actions[bot] 7347ae8f9d Bump versions for v13.09 2026-11-12 19:07:47 +00:00
Lauri Ojansivu 6cbb026f14 Prepare v13.09 release 2026-11-12 21:06:44 +02:00
Lauri Ojansivu 80253cf5e1 Merge remote-tracking branch 'origin/main' 2026-11-12 21:06:21 +02:00
Lauri Ojansivu d8fc23a4f4 CHANGELOG: snap-auth-check retries installing snapcraft.
Thanks to xet7 !
2026-11-12 21:02:13 +02:00
Lauri Ojansivu 534646347c Release: snap-auth-check retries installing snapcraft, as the build job does.
The v13.08 release stopped in snap-auth-check before it asked the Snap Store
anything: "cannot install system snap snapd: Post
https://api.snapcraft.io/v2/snaps/refresh: ... Client.Timeout exceeded while
awaiting headers". The job installed snapcraft once, while the snap build
job already retried five times, 30 seconds apart. It retries the same way now,
and when every attempt fails it says the store did not answer - not that
SNAP_AUTH is wrong.

tests/snapAuthPreflight.test.cjs fails on any snapcraft install in any
workflow without the five-attempt retry, and on the outage being reported as
a credential problem.

Thanks to xet7 !
2026-11-12 21:01:37 +02:00
13 changed files with 147 additions and 39 deletions

No files matched your search

+26 -4
View File
@@ -4533,7 +4533,10 @@ jobs:
snap-auth-check:
needs: [prepare]
runs-on: ubuntu-24.04
timeout-minutes: 10
# Room for all five snapcraft install attempts (each at most 3 minutes,
# 30 s apart) and the whoami after them: at 10 minutes (v13.09) the job
# was cancelled during the third.
timeout-minutes: 25
steps:
- name: Ask the Snap Store whether SNAP_AUTH is usable
env:
@@ -4557,7 +4560,23 @@ jobs:
;;
esac
sudo snap install snapcraft --classic
# The Snap Store has bad minutes - a rate limit, or (v13.07) a refresh
# that timed out - so the install is retried as the build job's is;
# an outage is said as one, not as a broken credential. Each attempt
# is bounded: in v13.09 the third hung silently until the job was
# cancelled. An attempt cut short leaves snapd's install change
# running, so it is aborted before the next.
installed=""
for i in 1 2 3 4 5; do
if timeout 180 sudo snap install snapcraft --classic; then installed=1; break; fi
sudo snap abort --last=install >/dev/null 2>&1 || true
echo "snapcraft install attempt $i/5 failed (Snap Store unreachable, throttling or hanging); retrying in 30s..."
sleep 30
done
if [ -z "$installed" ]; then
echo "::error::snapcraft could not be installed after 5 attempts: the Snap Store did not answer. That is the store, not SNAP_AUTH - re-run the job."
exit 1
fi
# whoami writes its answer to stdout and its complaint to stderr; both
# matter, so both are captured.
@@ -4954,8 +4973,11 @@ jobs:
run: |
set -uo pipefail
for i in 1 2 3 4 5; do
sudo snap install snapcraft --classic && exit 0
echo "snapcraft install attempt $i/5 failed (Snap Store throttle?); retrying in 30s..."
# Bounded, as snap-auth-check's: a hanging store is a failed
# attempt, not a job that waits until it is cancelled.
timeout 180 sudo snap install snapcraft --classic && exit 0
sudo snap abort --last=install >/dev/null 2>&1 || true
echo "snapcraft install attempt $i/5 failed (Snap Store throttle or hang?); retrying in 30s..."
sleep 30
done
echo "::error::snapcraft install failed after 5 attempts (Snap Store rate limit)."
+49
View File
@@ -124,6 +124,55 @@ its reason.
</details>
# v13.10 2026-11-13 WeKan ® release
**In short:** The release's **Snap Store** credential check bounds each
snapcraft install attempt, so a Snap Store that hangs no longer stops a release.
This release has the following developer-tooling fix:
**Release builds** - the snap jobs.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/560ff74a79f8c998bd0aa4fd63664155eecd5f28">Every snapcraft install attempt is bounded, and snap-auth-check has room for all five</a>. Thanks to xet7.</summary>
In the v13.09 release the Snap Store failed snap-auth-check's first two
snapcraft install attempts and then let the third hang with no output, until
the job's 10-minute timeout cancelled it - the retry never got its remaining
turns. Each `snap install snapcraft` in the release workflow now runs under
`timeout 180`, an attempt cut short is aborted (`snap abort --last=install`)
so the next one does not meet snapd's change still in progress, and
snap-auth-check's job timeout is 25 minutes, enough for all five attempts.
`tests/snapAuthPreflight.test.cjs` fails on an unbounded install, a retry
without the abort, or a job timeout that cannot hold five attempts.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v13.09 2026-11-12 WeKan ® release
**In short:** The release's **Snap Store** credential check retries installing
snapcraft, so one Snap Store timeout no longer stops a release.
This release has the following developer-tooling fix:
**Release builds** - the snap jobs.
<details>
<summary><a href="https://github.com/wekan/wekan/commit/534646347c4b6467f539cb01171487d27fc7ddc7">snap-auth-check retries installing snapcraft, as the snap build job does</a>. Thanks to xet7.</summary>
The v13.08 release stopped in snap-auth-check before it asked the Snap Store
anything: the one `snap install snapcraft` timed out reaching api.snapcraft.io,
while the snap build job already retried five times. The check retries the
same way now, and when every attempt fails it says the store did not answer
rather than that SNAP_AUTH is wrong. `tests/snapAuthPreflight.test.cjs` fails on
any snapcraft install in any workflow without the retry.
</details>
Thanks to above GitHub users for their contributions and translators for their translations.
# v13.08 2026-11-12 WeKan ® release
**In short:** The **REST API** creates a card under the **parent** it is given,
+14 -18
View File
@@ -5,6 +5,20 @@ each one changed and the project status are in
Written by `node releases/changelog-short.mjs` from CHANGELOG-big.md:
make changes there.
# v13.10 2026-11-13 WeKan ® release
The release's **Snap Store** credential check bounds each
snapcraft install attempt, so a Snap Store that hangs no longer stops a release.
[All changes in v13.10](CHANGELOG-big.md#v1310-2026-11-13-wekan--release)
# v13.09 2026-11-12 WeKan ® release
The release's **Snap Store** credential check retries installing
snapcraft, so one Snap Store timeout no longer stops a release.
[All changes in v13.09](CHANGELOG-big.md#v1309-2026-11-12-wekan--release)
# v13.08 2026-11-12 WeKan ® release
The **REST API** creates a card under the **parent** it is given,
@@ -36,21 +50,3 @@ and added without an error, and clearing a card **date** no longer passes as a
date set to the rules, the due date count and the activity feed.
[All changes in v13.06](CHANGELOG-big.md#v1306-2026-11-11-wekan--release)
# v13.05 2026-11-10 WeKan ® release
WeKan is updated to **Meteor 3.6**. The **Android** bundles
build again, after v13.04's npm retry broke their install, and the **Super
Productivity** export no longer fails for a board with a card whose list is
archived.
[All changes in v13.05](CHANGELOG-big.md#v1305-2026-11-10-wekan--release)
# v13.04 2026-11-09 WeKan ® release
**ListLockBleed** is fixed: when a list refuses a role write
access, that refusal now also holds for the checklist and checklist-item REST
routes. The **Sandstorm** and **Android** bundles retry their npm install when
github.com is briefly unavailable.
[All changes in v13.04](CHANGELOG-big.md#v1304-2026-11-09-wekan--release)
+1 -1
View File
@@ -38,7 +38,7 @@ FROM --platform=$BUILDPLATFORM debian:trixie AS bundle
ARG TARGETARCH
ARG TARGETVARIANT
ARG VERSION=13.08
ARG VERSION=13.10
ARG DEBIAN_FRONTEND=noninteractive
COPY --chmod=755 releases/check-telemetry.py /tmp/check-telemetry.py
+1 -1
View File
@@ -1,5 +1,5 @@
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
appVersion: "v13.08.0"
appVersion: "v13.10.0"
files:
userUploads:
- README.md
@@ -10,7 +10,7 @@ This is without container (without Docker or Snap).
Right click and download files 1-4:
1. [wekan-13.08-win64.zip](https://github.com/wekan/wekan/releases/download/v13.08/wekan-13.08-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
1. [wekan-13.10-win64.zip](https://github.com/wekan/wekan/releases/download/v13.10/wekan-13.10-win64.zip) or newest available at https://github.com/wekan/wekan/releases/
2. [node.exe](https://nodejs.org/dist/latest-v26.x/win-x64/node.exe)
@@ -22,7 +22,7 @@ Right click and download files 1-4:
6. Double click `mongodb-windows-x86_64-7.0.34-signed.msi` . In installer, uncheck downloading MongoDB compass.
7. Unzip `wekan-13.08-win64.zip` , inside it is directory `bundle`, to it copy other files:
7. Unzip `wekan-13.10-win64.zip` , inside it is directory `bundle`, to it copy other files:
```
bundle (directory)
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "wekan",
"version": "v13.08.0",
"version": "v13.10.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wekan",
"version": "v13.08.0",
"version": "v13.10.0",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "wekan",
"version": "v13.08.0",
"version": "v13.10.0",
"description": "Open-Source kanban",
"private": true,
"repository": {
+3 -3
View File
@@ -3,7 +3,7 @@
<head>
<meta charset="utf8" />
<title>WeKan REST API v13.08</title>
<title>WeKan REST API v13.10</title>
<!-- needed for adaptive design -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
@@ -494,11 +494,11 @@ data-styled.g652[id="sc-LDhwn"]{content:"cirFq,"}/*!sc*/
<body>
<div id="redoc"><div class="sc-jlWaFk kDulYG redoc light" style="--navbar-height:0px;--navbar-stack-height:0px"><div hidden=""><script>try{var r=document.querySelectorAll(".redoc");r=r[r.length-1];var h=document.documentElement,p=h.classList,a=[h.getAttribute("data-bs-theme"),h.getAttribute("data-theme")];var m=p.contains("dark")||a.indexOf("dark")>-1?"dark":p.contains("light")||a.indexOf("light")>-1?"light":localStorage.getItem("redoc.colorMode");if(m!=="light"&&m!=="dark")m=matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";r.classList.remove("light","dark");r.classList.add(m)}catch(e){}</script></div><div class="sc-NPrTd fpSCXb menu-content"><div class="sc-bJapvR eXtYur"><div data-testid="search-trigger" class="sc-eavxOQ bStpwo"><div class="sc-dGYDtq hRGWCd"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" data-component-name="icons/SearchIcon/SearchIcon" class="sc-gJaedx dpfGSp"><path d="M14.5 13.7931L10.724 10.017C11.6313 8.9277 12.0838 7.5305 11.9872 6.11608C11.8907 4.70165 11.2525 3.37891 10.2055 2.423C9.15857 1.4671 7.78336 0.951637 6.36602 0.983845C4.94867 1.01605 3.5983 1.59345 2.59582 2.59593C1.59335 3.5984 1.01595 4.94877 0.983738 6.36612C0.95153 7.78347 1.46699 9.15867 2.4229 10.2057C3.3788 11.2526 4.70155 11.8908 6.11597 11.9873C7.53039 12.0839 8.92759 11.6314 10.0169 10.7241L13.793 14.5001L14.5 13.7931ZM2.00001 6.50012C2.00001 5.6101 2.26393 4.74007 2.7584 4.00005C3.25286 3.26003 3.95567 2.68325 4.77794 2.34266C5.6002 2.00207 6.505 1.91295 7.37792 2.08658C8.25083 2.26022 9.05266 2.6888 9.68199 3.31814C10.3113 3.94747 10.7399 4.7493 10.9135 5.62221C11.0872 6.49513 10.9981 7.39993 10.6575 8.22219C10.3169 9.04446 9.7401 9.74726 9.00008 10.2417C8.26006 10.7362 7.39003 11.0001 6.50001 11.0001C5.30694 10.9988 4.16312 10.5243 3.31949 9.68064C2.47587 8.83701 2.00133 7.69319 2.00001 6.50012Z"></path></svg><span>Loading...</span></div></div></div><div class="sc-kLsiYl kAUzfx"><ul data-component-name="Menu/Menu" class="sc-jfJzNu hoWuXt"><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-default" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="true" class="sc-cToEys eWEtkC"><div class="sc-fIruOr dBwuTA"><span class="sc-gwVKcS efjekG"><span data-text="WeKan REST API" class="sc-hgJgCR dWgUkd">WeKan REST API</span></span></div></li></a></div><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-default" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/section/production-security-concerns" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-cToEys iVTRMP"><div class="sc-fIruOr dBwuTA"><span class="sc-gwVKcS efjekG"><span data-text="Production Security Concerns" class="sc-hgJgCR dlVNdD">Production Security Concerns</span></span></div></li></a></div><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-group" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/login" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-cToEys jYycQW"><div class="sc-dGPMcj PCvEP"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-kLEbxe eRqACJ"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-fIruOr dBwuTA"><span class="sc-gwVKcS efjekG"><span data-text="Login" class="sc-hgJgCR dlVNdD">Login</span></span></div></li></a><div style="display:none;height:0px;overflow:hidden" class="sc-fKDFlh joxUYR"></div></div><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-group" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/attachmentstoragesettings" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-cToEys jYycQW"><div class="sc-dGPMcj PCvEP"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-kLEbxe eRqACJ"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-fIruOr dBwuTA"><span class="sc-gwVKcS efjekG"><span data-text="AttachmentStorageSettings" class="sc-hgJgCR dlVNdD">AttachmentStorageSettings</span></span></div></li></a><div style="display:none;height:0px;overflow:hidden" class="sc-fKDFlh joxUYR"></div></div><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-group" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/settings" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-cToEys jYycQW"><div class="sc-dGPMcj PCvEP"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-defLine truncated
<div id="redoc"><div class="sc-jlWaFk kDulYG redoc light" style="--navbar-height:0px;--navbar-stack-height:0px"><div hidden=""><script>try{var r=document.querySelectorAll(".redoc");r=r[r.length-1];var h=document.documentElement,p=h.classList,a=[h.getAttribute("data-bs-theme"),h.getAttribute("data-theme")];var m=p.contains("dark")||a.indexOf("dark")>-1?"dark":p.contains("light")||a.indexOf("light")>-1?"light":localStorage.getItem("redoc.colorMode");if(m!=="light"&&m!=="dark")m=matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light";r.classList.remove("light","dark");r.classList.add(m)}catch(e){}</script></div><div class="sc-NPrTd fpSCXb menu-content"><div class="sc-bJapvR eXtYur"><div data-testid="search-trigger" class="sc-eavxOQ bStpwo"><div class="sc-dGYDtq hRGWCd"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" data-component-name="icons/SearchIcon/SearchIcon" class="sc-gJaedx dpfGSp"><path d="M14.5 13.7931L10.724 10.017C11.6313 8.9277 12.0838 7.5305 11.9872 6.11608C11.8907 4.70165 11.2525 3.37891 10.2055 2.423C9.15857 1.4671 7.78336 0.951637 6.36602 0.983845C4.94867 1.01605 3.5983 1.59345 2.59582 2.59593C1.59335 3.5984 1.01595 4.94877 0.983738 6.36612C0.95153 7.78347 1.46699 9.15867 2.4229 10.2057C3.3788 11.2526 4.70155 11.8908 6.11597 11.9873C7.53039 12.0839 8.92759 11.6314 10.0169 10.7241L13.793 14.5001L14.5 13.7931ZM2.00001 6.50012C2.00001 5.6101 2.26393 4.74007 2.7584 4.00005C3.25286 3.26003 3.95567 2.68325 4.77794 2.34266C5.6002 2.00207 6.505 1.91295 7.37792 2.08658C8.25083 2.26022 9.05266 2.6888 9.68199 3.31814C10.3113 3.94747 10.7399 4.7493 10.9135 5.62221C11.0872 6.49513 10.9981 7.39993 10.6575 8.22219C10.3169 9.04446 9.7401 9.74726 9.00008 10.2417C8.26006 10.7362 7.39003 11.0001 6.50001 11.0001C5.30694 10.9988 4.16312 10.5243 3.31949 9.68064C2.47587 8.83701 2.00133 7.69319 2.00001 6.50012Z"></path></svg><span>Loading...</span></div></div></div><div class="sc-kLsiYl kAUzfx"><ul data-component-name="Menu/Menu" class="sc-jfJzNu hoWuXt"><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-default" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="true" class="sc-cToEys eWEtkC"><div class="sc-fIruOr dBwuTA"><span class="sc-gwVKcS efjekG"><span data-text="WeKan REST API" class="sc-hgJgCR dWgUkd">WeKan REST API</span></span></div></li></a></div><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-default" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/section/production-security-concerns" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-cToEys iVTRMP"><div class="sc-fIruOr dBwuTA"><span class="sc-gwVKcS efjekG"><span data-text="Production Security Concerns" class="sc-hgJgCR dlVNdD">Production Security Concerns</span></span></div></li></a></div><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-group" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/login" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-cToEys jYycQW"><div class="sc-dGPMcj PCvEP"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-kLEbxe eRqACJ"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-fIruOr dBwuTA"><span class="sc-gwVKcS efjekG"><span data-text="Login" class="sc-hgJgCR dlVNdD">Login</span></span></div></li></a><div style="display:none;height:0px;overflow:hidden" class="sc-fKDFlh joxUYR"></div></div><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-group" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/attachmentstoragesettings" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-cToEys jYycQW"><div class="sc-dGPMcj PCvEP"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-default" data-component-name="icons/ChevronRightIcon/ChevronRightIcon" class="sc-kLEbxe eRqACJ"><path d="M11 8L6.00002 13L5.30002 12.3L9.60002 8L5.30002 3.7L6.00002 3L11 8Z"></path></svg></div><div class="sc-fIruOr dBwuTA"><span class="sc-gwVKcS efjekG"><span data-text="AttachmentStorageSettings" class="sc-hgJgCR dlVNdD">AttachmentStorageSettings</span></span></div></li></a><div style="display:none;height:0px;overflow:hidden" class="sc-fKDFlh joxUYR"></div></div><div data-component-name="Menu/MenuItem" class="sc-jEekwy kJsUv menu-item-type-group" role="listitem"><a class="sc-gzhUzI kKmXTr" href="/settings" data-discover="true"><li role="none" data-testid="menu-item-label" data-active="false" class="sc-cToEys jYycQW"><div class="sc-dGPMcj PCvEP"><svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" color="--tree-content-color-defLine truncated
<script type="module">
import { hydrate } from "https://cdn.redocly.com/redoc/v3.1.0/bundles/redoc.standalone.js";
const __redoc_definition = {"openapi":"3.2.0","info":{"title":"WeKan REST API","version":"v13.08","description":"The REST API allows you to control and extend WeKan with ease.\n\nIf you are an end-user and not a dev or a tester, [create an issue](https://github.com/wekan/wekan/issues/new) to request new APIs.\n\n> All API calls in the documentation are made using `curl`. However, you are free to use Java / Python / PHP / Golang / Ruby / Swift / Objective-C / Rust / Scala / C# or any other programming languages.\n\n# Production Security Concerns\nWhen calling a production WeKan server, ensure it is running via HTTPS and has a valid SSL Certificate. The login method requires you to post your username and password in plaintext, which is why we highly suggest only calling the REST login api over HTTPS. Also, few things to note:\n\n* Only call via HTTPS\n* Implement a timed authorization token expiration strategy\n* Ensure the calling user only has permissions for what they are calling and no more\n"},"paths":{"/users/login":{"post":{"operationId":"login","summary":"Login with REST API","tags":["Login"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}}},"description":"Login credentials","required":true},"responses":{"200":{"description":"Successful authentication","content":{"*/*":{"schema":{"type":"object","required":["id","token","tokenExpires"],"properties":{"id":{"type":"string","description":"User ID"},"token":{"type":"string","description":"Authentication token\n"},"tokenExpires":{"type":"string","format":"date-time","description":"Token expiration date\n"}}}}}},"400":{"description":"Error in authentication\n","content":{"*/*":{"schema":{"type":"object","properties":{"error":{"type":"string"},"reason":{"type":"string"}}}}}},"default":{"description":"Error in authentication\n"}}}},"/users/register":{"post":{"operationId":"register","summary":"Register with REST API","description":"Notes:\n - You will need to provide the token for any of the authenticated methods.\n","tags":["Login"],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"},"email":{"description":"Your email\n","type":"string"}},"required":["username","password","email"]}}},"required":true},"responses":{"200":{"description":"Successful registration","content":{"*/*":{"schema":{"items":{"properties":{"id":{"type":"string"},"token":{"type":"string"},"tokenExpires":{"type":"string"}}}}}}},"400":{"description":"Error in registration\n","content":{"*/*":{"schema":{"items":{"properties":{"error":{"type":"number"},"reason":{"type":"string"}}}}}}},"default":{"description":"Error in registration\n"}}}},"/api/admin/attachment-settings":{"get":{"operationId":"get_attachment_settings","summary":"Get the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. Returns the Admin Panel >\n Attachments settings document, including `limitSettings.attachmentsUploadBlocked`\n and `limitSettings.avatarsUploadBlocked` plus the size limits. Cloud-storage\n secret keys (S3 secretAccessKey, Azure accountKey/connectionString, GCS\n credentials) are masked and never returned; a boolean `\u003cfield>Set` marker\n shows whether a value exists.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}},"put":{"operationId":"update_attachment_settings","summary":"Update the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. The request body is a\n partial settings object (for example\n `{\"limitSettings\": {\"avatarsUploadBlocked\": true}}`). It is applied through\n the same update path as the `updateAttachmentStorageSettings` Meteor method,\n so validation and `$set` semantics are identical: cloud-storage secrets left\n blank are preserved. The masked, updated settings document is returned.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}}},"/api/admin/domains":{"get":{"operationId":"get_admin_domains","summary":"List email domains with their user counts (GlobalAdmin)","description":"Only the global admin can call this. CountsLine truncated
const __redoc_definition = {"openapi":"3.2.0","info":{"title":"WeKan REST API","version":"v13.10","description":"The REST API allows you to control and extend WeKan with ease.\n\nIf you are an end-user and not a dev or a tester, [create an issue](https://github.com/wekan/wekan/issues/new) to request new APIs.\n\n> All API calls in the documentation are made using `curl`. However, you are free to use Java / Python / PHP / Golang / Ruby / Swift / Objective-C / Rust / Scala / C# or any other programming languages.\n\n# Production Security Concerns\nWhen calling a production WeKan server, ensure it is running via HTTPS and has a valid SSL Certificate. The login method requires you to post your username and password in plaintext, which is why we highly suggest only calling the REST login api over HTTPS. Also, few things to note:\n\n* Only call via HTTPS\n* Implement a timed authorization token expiration strategy\n* Ensure the calling user only has permissions for what they are calling and no more\n"},"paths":{"/users/login":{"post":{"operationId":"login","summary":"Login with REST API","tags":["Login"],"requestBody":{"content":{"application/json":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}},"application/x-www-form-urlencoded":{"schema":{"type":"object","required":["username","password"],"properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"}}}}},"description":"Login credentials","required":true},"responses":{"200":{"description":"Successful authentication","content":{"*/*":{"schema":{"type":"object","required":["id","token","tokenExpires"],"properties":{"id":{"type":"string","description":"User ID"},"token":{"type":"string","description":"Authentication token\n"},"tokenExpires":{"type":"string","format":"date-time","description":"Token expiration date\n"}}}}}},"400":{"description":"Error in authentication\n","content":{"*/*":{"schema":{"type":"object","properties":{"error":{"type":"string"},"reason":{"type":"string"}}}}}},"default":{"description":"Error in authentication\n"}}}},"/users/register":{"post":{"operationId":"register","summary":"Register with REST API","description":"Notes:\n - You will need to provide the token for any of the authenticated methods.\n","tags":["Login"],"requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"type":"object","properties":{"username":{"description":"Your username\n","type":"string"},"password":{"description":"Your password\n","type":"string","format":"password"},"email":{"description":"Your email\n","type":"string"}},"required":["username","password","email"]}}},"required":true},"responses":{"200":{"description":"Successful registration","content":{"*/*":{"schema":{"items":{"properties":{"id":{"type":"string"},"token":{"type":"string"},"tokenExpires":{"type":"string"}}}}}}},"400":{"description":"Error in registration\n","content":{"*/*":{"schema":{"items":{"properties":{"error":{"type":"number"},"reason":{"type":"string"}}}}}}},"default":{"description":"Error in registration\n"}}}},"/api/admin/attachment-settings":{"get":{"operationId":"get_attachment_settings","summary":"Get the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. Returns the Admin Panel >\n Attachments settings document, including `limitSettings.attachmentsUploadBlocked`\n and `limitSettings.avatarsUploadBlocked` plus the size limits. Cloud-storage\n secret keys (S3 secretAccessKey, Azure accountKey/connectionString, GCS\n credentials) are masked and never returned; a boolean `\u003cfield>Set` marker\n shows whether a value exists.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}},"put":{"operationId":"update_attachment_settings","summary":"Update the attachment storage / upload-block settings (GlobalAdmin)","description":"Only the global admin can call this. The request body is a\n partial settings object (for example\n `{\"limitSettings\": {\"avatarsUploadBlocked\": true}}`). It is applied through\n the same update path as the `updateAttachmentStorageSettings` Meteor method,\n so validation and `$set` semantics are identical: cloud-storage secrets left\n blank are preserved. The masked, updated settings document is returned.\n","tags":["AttachmentStorageSettings","Settings"],"security":[{"UserSecurity":[]}],"responses":{"200":{"description":"200 response","content":{"application/json":{"schema":{"type":"Object"}}}}}}},"/api/admin/domains":{"get":{"operationId":"get_admin_domains","summary":"List email domains with their user counts (GlobalAdmin)","description":"Only the global admin can call this. CountsLine truncated
const __redoc_options = {"skipBundle":true,"disableTelemetry":false};
hydrate(__redoc_definition, __redoc_options, document.getElementById('redoc'));
+1 -1
View File
@@ -1,7 +1,7 @@
swagger: '2.0'
info:
title: WeKan REST API
version: v13.08
version: v13.10
description: |
The REST API allows you to control and extend WeKan with ease.
+2 -2
View File
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
appTitle = (defaultText = "Wekan"),
# The name of the app as it is displayed to the user.
appVersion = 1308,
appVersion = 1310,
# Increment this for every release.
appMarketingVersion = (defaultText = "13.08~2026-11-12"),
appMarketingVersion = (defaultText = "13.10~2026-11-13"),
# Human-readable presentation of the app version.
minUpgradableAppVersion = 0,
+4 -4
View File
@@ -19,7 +19,7 @@
# base: core24 (not core26) · no build-base: devel · grade: stable
# ─────────────────────────────────────────────────────────────────────────────
name: wekan
version: '13.08'
version: '13.10'
base: core24
confinement: strict
grade: stable
@@ -703,18 +703,18 @@ parts:
armhf) WEKAN_ARCH="armhf" ;;
*) echo "Unsupported architecture: ${CRAFT_ARCH_BUILD_FOR}"; exit 1 ;;
esac
WEKAN_ZIP="wekan-13.08-${WEKAN_ARCH}.zip"
WEKAN_ZIP="wekan-13.10-${WEKAN_ARCH}.zip"
echo "Cleaning environment first"
rm -rf .build
mkdir .build
cd .build
#wget https://github.com/wekan/wekan/releases/download/v13.08/wekan-13.08-amd64.zip
#wget https://github.com/wekan/wekan/releases/download/v13.10/wekan-13.10-amd64.zip
# Retry: a release asset can 404 for a short while right after it is
# uploaded (CDN/propagation lag), and a plain wget treated that as
# fatal. --retry-on-http-error covers the 404/5xx window; a genuinely
# missing bundle still fails after the tries are spent.
wget --tries=20 --waitretry=20 --retry-on-http-error=404,403,500,502,503 \
"https://github.com/wekan/wekan/releases/download/v13.08/${WEKAN_ZIP}"
"https://github.com/wekan/wekan/releases/download/v13.10/${WEKAN_ZIP}"
unzip "${WEKAN_ZIP}"
python3 ../releases/check-telemetry.py --bundle bundle
rm "${WEKAN_ZIP}"
+41
View File
@@ -101,6 +101,47 @@ test('the credential itself is never printed', () => {
assert.ok(/echo "\$out"/.test(job), "only whoami's answer is");
});
test('every snapcraft install in the workflows is retried', () => {
// v13.07: snap-auth-check installed snapcraft once, the Snap Store timed out
// ("Client.Timeout exceeded while awaiting headers") and the whole release
// check failed, while the build job's install already retried five times.
const dir = path.join(__dirname, '..', '.github', 'workflows');
for (const f of fs.readdirSync(dir).filter(n => /\.ya?ml$/.test(n))) {
const lines = fs.readFileSync(path.join(dir, f), 'utf8').split('\n');
lines.forEach((line, i) => {
if (!/snap install snapcraft/.test(line) || /^\s*#/.test(line)) return;
const before = lines.slice(Math.max(0, i - 3), i).join('\n');
assert.ok(/for i in 1 2 3 4 5; do/.test(before),
`${f}:${i + 1} installs snapcraft without the five-attempt retry`);
});
}
assert.ok(/the Snap Store did not answer. That is the store, not SNAP_AUTH/.test(job),
'an outage is not reported as a credential problem');
});
test('every snapcraft install attempt is bounded, and the job has room for all five', () => {
// v13.09: the third attempt hung with no output until snap-auth-check's
// 10-minute timeout cancelled the job - the retry never got its turn.
const dir = path.join(__dirname, '..', '.github', 'workflows');
for (const f of fs.readdirSync(dir).filter(n => /\.ya?ml$/.test(n))) {
const lines = fs.readFileSync(path.join(dir, f), 'utf8').split('\n');
lines.forEach((line, i) => {
if (!/snap install snapcraft/.test(line) || /^\s*#/.test(line)) return;
const m = line.match(/timeout (\d+) sudo snap install snapcraft/);
assert.ok(m, `${f}:${i + 1} installs snapcraft without a time limit per attempt`);
const after = lines.slice(i + 1, i + 3).join('\n');
assert.ok(/snap abort --last=install/.test(after),
`${f}:${i + 1} retries without aborting the attempt that was cut short`);
});
}
// Negative: the job's own limit must not end the retry before five attempts.
const perAttempt = Number((job.match(/timeout (\d+) sudo snap install snapcraft/) || [])[1]);
const minutes = Number((job.match(/timeout-minutes: (\d+)/) || [])[1]);
assert.ok(perAttempt > 0 && minutes > 0, 'both limits are set');
assert.ok(minutes * 60 >= 5 * (perAttempt + 30) + 120,
`snap-auth-check's ${minutes} minutes cannot hold five ${perAttempt}-second attempts`);
});
test('a shell that keeps going long enough to classify the failure', () => {
// `set -e` around the whoami call would kill the step at the failure, before
// the case that says WHICH failure it was.