1name: CI
2
3on:
4 push:
5 branches: [master]
6 pull_request:
7 branches: [master]
8
9jobs:
10 build:
11 runs-on: ${{ matrix.os }}
12 strategy:
13 matrix:
14 os: [ubuntu-latest, windows-latest, macos-latest]
15 steps:
16 - uses: actions/checkout@v6
17
18 - name: Set up Go
19 uses: actions/setup-go@v6
20 with:
21 go-version: "1.26.3"
22
23 - name: Install system dependencies
24 if: runner.os == 'Linux'
25 run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
26
27 - name: Tidy modules
28 run: go mod tidy
29
30 - name: Test
31 run: go test -v ./...
32
33 - name: Build
34 run: go build -v ./...
35
36 lint:
37 runs-on: ubuntu-latest
38 steps:
39 - uses: actions/checkout@v6
40
41 - name: Set up Go
42 uses: actions/setup-go@v6
43 with:
44 go-version: "1.26.3"
45
46 - name: Install system dependencies
47 run: sudo apt-get update && sudo apt-get install -y libpcsclite-dev
48
49 - name: Check formatting
50 run: |
51 unformatted=$(gofmt -l .)
52 if [ -n "$unformatted" ]; then
53 echo "::error::The following files are not formatted with gofmt:"
54 echo "$unformatted"
55 exit 1
56 fi
57
58 - name: Vet
59 run: go vet ./...
60
61 - name: golangci-lint
62 uses: golangci/golangci-lint-action@v7
63 with:
64 version: v2.12.2
65 args: --timeout=10m --build-tags=integration
66 only-new-issues: false
67
68 mod-tidy:
69 runs-on: ubuntu-latest
70 steps:
71 - uses: actions/checkout@v6
72
73 - name: Set up Go
74 uses: actions/setup-go@v6
75 with:
76 go-version: "1.26.3"
77
78 - name: Check go.mod and go.sum are tidy
79 run: |
80 go mod tidy
81 if ! git diff --quiet go.mod go.sum; then
82 echo "::error::go.mod or go.sum are not tidy. Run 'go mod tidy' and commit the changes."
83 git diff go.mod go.sum
84 exit 1
85 fi
86
87 website:
88 runs-on: ubuntu-latest
89 defaults:
90 run:
91 working-directory: docs
92 steps:
93 - uses: actions/checkout@v6
94
95 - name: Set up Node.js
96 uses: actions/setup-node@v6
97 with:
98 node-version: "24"
99 cache: npm
100 cache-dependency-path: docs/package-lock.json
101
102 - name: Install dependencies
103 run: npm ci
104
105 - name: Build
106 run: npx docusaurus build
107
108 snap:
109 runs-on: ubuntu-latest
110 steps:
111 - uses: actions/checkout@v6
112
113 - name: Validate snapcraft.yaml
114 run: |
115 sudo snap install snapcraft --classic
116 # Verify snapcraft can parse the project file
117 snapcraft list-plugins
118 # Validate YAML structure and required fields
119 python3 << 'PYEOF'
120 import yaml, sys
121
122 with open("snapcraft.yaml") as f:
123 snap = yaml.safe_load(f)
124
125 errors = []
126 for field in ("name", "base", "summary", "description", "parts"):
127 if field not in snap:
128 errors.append(f"Missing required field: {field}")
129
130 if "apps" in snap:
131 for app_name, app in snap["apps"].items():
132 if "command" not in app:
133 errors.append(f"App '{app_name}' missing 'command'")
134
135 if "parts" in snap:
136 for part_name, part in snap["parts"].items():
137 if "plugin" not in part and "override-build" not in part:
138 errors.append(f"Part '{part_name}' missing 'plugin' or 'override-build'")
139
140 if errors:
141 for e in errors:
142 print(f"::error::{e}", file=sys.stderr)
143 sys.exit(1)
144
145 print("snapcraft.yaml is valid.")
146 PYEOF
147
148 flatpak:
149 runs-on: ubuntu-latest
150 steps:
151 - uses: actions/checkout@v6
152
153 - name: Install dependencies
154 run: |
155 sudo apt-get update
156 sudo apt-get install -y python3-pip
157 pip3 install PyYAML
158
159 - name: Validate Flatpak manifest YAML
160 run: python3 -c "import yaml, sys; yaml.safe_load(open('com.floatpane.matcha.yaml'))"
161
162 - name: Check Flatpak manifest structure
163 run: |
164 python3 << 'EOF'
165 import yaml, sys
166
167 with open("com.floatpane.matcha.yaml") as f:
168 manifest = yaml.safe_load(f)
169
170 errors = []
171 for field in ("id", "runtime", "runtime-version", "sdk", "command", "modules"):
172 if field not in manifest:
173 errors.append(f"Missing required field: {field}")
174
175 if "modules" in manifest:
176 for mod in manifest["modules"]:
177 if "name" not in mod:
178 errors.append(f"Module missing 'name' field: {mod}")
179 if "sources" not in mod and "buildsystem" not in mod:
180 errors.append(f"Module '{mod.get('name', '?')}' missing 'sources' or 'buildsystem'")
181
182 if errors:
183 for e in errors:
184 print(f"::error::{e}", file=sys.stderr)
185 sys.exit(1)
186
187 print("Flatpak manifest is valid.")
188 EOF
189
190 nix:
191 runs-on: ubuntu-latest
192 steps:
193 - uses: actions/checkout@v6
194
195 - name: Install Nix
196 uses: cachix/install-nix-action@v31
197 with:
198 nix_path: nixpkgs=channel:nixpkgs-unstable
199
200 - name: Check flake
201 run: nix flake check --no-build
202
203 lua-plugins:
204 runs-on: ubuntu-latest
205 steps:
206 - uses: actions/checkout@v6
207
208 - name: Install Lua
209 run: sudo apt-get update && sudo apt-get install -y lua5.4
210
211 - name: Check Lua syntax
212 run: |
213 failed=0
214 for f in plugins/*.lua; do
215 if ! luac -p "$f" 2>&1; then
216 echo "::error file=$f::Syntax error in $f"
217 failed=1
218 fi
219 done
220 exit $failed
221
222 goreleaser:
223 runs-on: ubuntu-latest
224 steps:
225 - uses: actions/checkout@v6
226 with:
227 fetch-depth: 0
228
229 - name: Set up Go
230 uses: actions/setup-go@v6
231 with:
232 go-version: "1.26.3"
233
234 - name: Install GoReleaser
235 uses: goreleaser/goreleaser-action@v7
236 with:
237 install-only: true
238
239 - name: Validate release config
240 run: goreleaser check -f .goreleaser.yml
241
242 - name: Validate nightly config
243 run: goreleaser check -f .goreleaser.nightly.yml