Repository navigation
145 lines (127 loc) · 5.24 KB
/
Copy pathci.yml
File metadata and controls
145 lines (127 loc) · 5.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# SPDX-License-Identifier: MIT
# The tests that need neither Docker nor a running cased. The acceptance suite
# (tests/test_acceptance.py) needs a real desktop container and stays local-only.
name: ci
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.12"
cache: pip
cache-dependency-path: requirements*.txt
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "22"
cache: npm
cache-dependency-path: web/package-lock.json
- name: Install deps
run: |
python -m venv .venv
.venv/bin/pip install -r requirements-dev.txt
- name: Lint
run: .venv/bin/ruff check --select F,E9 control-plane mcp image tests
- name: Unit tests (no Docker)
run: |
# Everything except the acceptance suite, which needs a real desktop
# container. Enumerated from disk so a new test file is never silently
# left out of CI.
fail=0
for f in tests/test_*.py; do
case "$f" in tests/test_acceptance.py) continue ;; esac
echo "--- $f"
.venv/bin/python "$f" || fail=1
done
exit $fail
- name: Drive UI tests
run: |
npm --prefix web ci --omit=dev # serve.mjs imports openai at module load
npm --prefix web test
- name: Shell scripts
run: .venv/bin/shellcheck -e SC1090 image/start.sh bin/case # SC1090: ~/.case/env is the user's
- name: Compose file
run: docker compose config -q
# deskd runs on Debian bookworm's Python in the image, against its own pins, not
# the control plane's. Test it there too.
deskd:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.11"
cache: pip
cache-dependency-path: image/requirements.txt
- name: deskd tests on the image's pins
run: |
python -m venv .venv
.venv/bin/pip install -r image/requirements.txt httpx==0.28.1
.venv/bin/python tests/test_deskd.py
# Case is dual-licensed and sold commercially, which is only possible if the
# project can sublicense every contribution. Deliberately no third-party CLA
# bot: the one everyone used was archived in March 2026, and a licensing gate
# is the last place to inherit an abandoned dependency. A contributor signs
# by adding their own username to CLA-SIGNERS in their first pull request.
cla:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Contributor has signed the CLA
env:
AUTHOR: ${{ github.event.pull_request.user.login }}
run: |
# No process substitution and POSIX classes only: this must behave the
# same in any shell anyone runs it in, including locally.
test -n "$AUTHOR" || { echo "no pull request author in the event"; exit 1; }
if grep -v '^[[:space:]]*#' CLA-SIGNERS | grep -qxF "$AUTHOR"; then
echo "$AUTHOR has signed the CLA."
exit 0
fi
cat <<EOF
$AUTHOR has not signed the CLA.
Case is dual-licensed (AGPL for the box, MIT for the clients) and is
also offered under a commercial license. That is only possible if the
project can sublicense every contribution, so we ask each contributor
to sign once. You keep your copyright: it is a license, not an
assignment.
To sign: read CLA.md, then add a line containing exactly
$AUTHOR
to the CLA-SIGNERS file, and push it as part of this pull request.
That is the whole process, and you never have to do it again.
EOF
exit 1
spdx:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- name: Every source file declares its license
run: |
# A plain pathspec's * crosses directories, so web/*.mjs covers web/ at any depth.
# The list is built first so a git failure fails the step instead of an empty loop.
files=$(git ls-files \
'control-plane/*.py' 'image/*.py' 'image/*.sh' \
'mcp/*.py' 'tests/*.py' 'web/*.mjs' 'web/*.html' 'bin/case')
missing=0
for f in $files; do
grep -q 'SPDX-License-Identifier' "$f" || { echo "no SPDX header: $f"; missing=1; }
done
[ "$missing" = 0 ] || {
echo "New files take the SPDX id of their directory. See LICENSE.md."
exit 1
}