Skip to content

Commit e8fc683

Browse files
committed
feat(ci): add db migration test workflow
Signed-off-by: kyteinsky <kyteinsky@gmail.com>
1 parent 5c961b4 commit e8fc683

1 file changed

Lines changed: 273 additions & 0 deletions

File tree

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
# SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
2+
# SPDX-License-Identifier: AGPL-3.0-or-later
3+
4+
name: Migration test
5+
6+
on:
7+
pull_request:
8+
branches:
9+
- main
10+
- stable*
11+
12+
env:
13+
APP_NAME: context_chat
14+
PHP_EXTENSIONS: bz2, ctype, curl, dom, fileinfo, gd, iconv, intl, json, libxml, mbstring, openssl, pcntl, posix, session, simplexml, xmlreader, xmlwriter, zip, zlib, sqlite, pdo_sqlite, pgsql, pdo_pgsql, mysql, pdo_mysql, oci8
15+
16+
permissions:
17+
contents: read
18+
19+
concurrency:
20+
group: migration-test-${{ github.head_ref || github.run_id }}
21+
cancel-in-progress: true
22+
23+
jobs:
24+
changes:
25+
runs-on: ubuntu-latest-low
26+
permissions:
27+
contents: read
28+
pull-requests: read
29+
30+
outputs:
31+
src: ${{ steps.changes.outputs.src }}
32+
33+
steps:
34+
- uses: dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
35+
id: changes
36+
continue-on-error: true
37+
with:
38+
filters: |
39+
src:
40+
- '.github/workflows/migration-test.yml'
41+
- 'lib/Migration/**'
42+
- 'lib/Repair/**'
43+
44+
migration-test:
45+
runs-on: ubuntu-latest
46+
47+
needs: changes
48+
if: needs.changes.outputs.src != 'false'
49+
50+
strategy:
51+
fail-fast: false
52+
matrix:
53+
include:
54+
- db: sqlite
55+
db-type: sqlite
56+
db-port: ''
57+
- db: pgsql
58+
db-type: pgsql
59+
db-port: '4445'
60+
- db: mysql
61+
db-type: mysql
62+
db-port: '4444'
63+
- db: mariadb
64+
db-type: mysql
65+
db-port: '4446'
66+
- db: oci21
67+
db-type: oci
68+
db-port: '1521'
69+
oci-version: '21'
70+
oci-flavour: xe
71+
oci-name: XE
72+
- db: oci23
73+
db-type: oci
74+
db-port: '1521'
75+
oci-version: '23'
76+
oci-flavour: free
77+
oci-name: FREE
78+
79+
name: Migration test ${{ matrix.db }}
80+
81+
steps:
82+
- name: Start postgres
83+
if: matrix.db == 'pgsql'
84+
run: |
85+
docker run -d --name db \
86+
-e POSTGRES_USER=root \
87+
-e POSTGRES_PASSWORD=rootpassword \
88+
-e POSTGRES_DB=nextcloud \
89+
-p 4445:5432 \
90+
postgres:17 # zizmor: ignore[unpinned-images]
91+
timeout 60 bash -c 'until docker exec db pg_isready -U root; do sleep 1; done'
92+
93+
- name: Start mysql
94+
if: matrix.db == 'mysql'
95+
run: |
96+
docker run -d --name db \
97+
-e MYSQL_ROOT_PASSWORD=rootpassword \
98+
-p 4444:3306 \
99+
mysql:8.4 # zizmor: ignore[unpinned-images]
100+
timeout 60 bash -c 'until docker exec db mysqladmin ping -prootpassword --silent; do sleep 1; done'
101+
102+
- name: Start mariadb
103+
if: matrix.db == 'mariadb'
104+
run: |
105+
docker run -d --name db \
106+
-e MARIADB_ROOT_PASSWORD=rootpassword \
107+
-p 4446:3306 \
108+
mariadb:11.4 # zizmor: ignore[unpinned-images]
109+
timeout 60 bash -c 'until docker exec db mariadb-admin ping -prootpassword --silent; do sleep 1; done'
110+
111+
- name: Start oracle
112+
if: startsWith(matrix.db, 'oci')
113+
run: |
114+
docker run -d --name db \
115+
-e ORACLE_PASSWORD=oracle \
116+
-p 1521:1521 \
117+
ghcr.io/gvenzl/oracle-${{ matrix.oci-flavour }}:${{ matrix.oci-version }} # zizmor: ignore[unpinned-images]
118+
timeout 300 bash -c 'until docker exec db healthcheck.sh; do sleep 5; done'
119+
120+
- name: Checkout server
121+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
122+
with:
123+
repository: nextcloud/server
124+
ref: ${{ github.base_ref == 'main' && 'master' || github.base_ref }}
125+
submodules: recursive
126+
persist-credentials: false
127+
128+
- name: Checkout viewer
129+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
130+
with:
131+
repository: nextcloud/viewer
132+
path: apps/viewer
133+
ref: ${{ github.base_ref == 'main' && 'master' || github.base_ref }}
134+
persist-credentials: false
135+
136+
- name: Set up php 8.2
137+
uses: shivammathur/setup-php@7c071dfe9dc99bdf297fa79cb49ea005b9fcadbc # 2.37.1
138+
with:
139+
php-version: '8.2'
140+
extensions: ${{ env.PHP_EXTENSIONS }}
141+
coverage: none
142+
ini-file: development
143+
ini-values: disable_functions=
144+
env:
145+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
146+
147+
- name: Checkout app and fetch all tags
148+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
149+
with:
150+
repository: nextcloud/${{ env.APP_NAME }}
151+
path: apps/${{ env.APP_NAME }}
152+
fetch-depth: 0
153+
persist-credentials: false
154+
155+
- name: Switch to previous release tag
156+
id: prev-tag
157+
working-directory: apps/${{ env.APP_NAME }}
158+
run: |
159+
PREV_TAG=$(git tag --sort=-version:refname | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
160+
if [ -z "$PREV_TAG" ]; then
161+
echo "No previous release tag found"
162+
exit 1
163+
fi
164+
echo "tag=${PREV_TAG}" >> $GITHUB_OUTPUT
165+
git checkout "$PREV_TAG"
166+
167+
- name: Set up Nextcloud (${{ matrix.db }})
168+
run: |
169+
mkdir -p data
170+
if [ "${{ matrix.db }}" = "sqlite" ]; then
171+
./occ maintenance:install --verbose \
172+
--database=sqlite --database-name=nextcloud \
173+
--admin-user admin --admin-pass admin
174+
elif [ "${{ matrix.db-type }}" = "oci" ]; then
175+
./occ maintenance:install --verbose \
176+
--database=oci \
177+
--database-name=${{ matrix.oci-name }} \
178+
--database-host=127.0.0.1 \
179+
--database-port=${{ matrix.db-port }} \
180+
--database-user=system \
181+
--database-pass=oracle \
182+
--admin-user admin --admin-pass admin
183+
else
184+
./occ maintenance:install --verbose \
185+
--database=${{ matrix.db-type }} \
186+
--database-name=nextcloud \
187+
--database-host=127.0.0.1 \
188+
--database-port=${{ matrix.db-port }} \
189+
--database-user=root \
190+
--database-pass=rootpassword \
191+
--admin-user admin --admin-pass admin
192+
fi
193+
./occ config:system:set debug --value true
194+
./occ config:system:set loglevel --value 1
195+
196+
- name: Enable app (previous version ${{ steps.prev-tag.outputs.tag }})
197+
run: ./occ app:enable --force ${{ env.APP_NAME }}
198+
199+
- name: Check if the previous version installed correctly
200+
run: |
201+
./occ status
202+
./occ app:list --output json | jq -e '.enabled | has("${{ env.APP_NAME }}")'
203+
./occ migrations:status ${{ env.APP_NAME }}
204+
205+
- name: Dump database before upgrade
206+
if: always()
207+
run: |
208+
if [ "${{ matrix.db }}" = "sqlite" ]; then
209+
cp data/nextcloud.db /tmp/${{ matrix.db }}_before.db
210+
elif [ "${{ matrix.db }}" = "pgsql" ]; then
211+
docker exec db pg_dump -U root nextcloud > /tmp/${{ matrix.db }}_before.sql
212+
elif [ "${{ matrix.db }}" = "mysql" ] || [ "${{ matrix.db }}" = "mariadb" ]; then
213+
docker exec db mariadb-dump -uroot -prootpassword nextcloud > /tmp/${{ matrix.db }}_before.sql
214+
elif [[ "${{ matrix.db }}" == oci* ]]; then
215+
docker exec db expdp system/oracle@${{ matrix.oci-name }} directory=DATA_PUMP_DIR dumpfile=${{ matrix.db }}_before.dmp logfile=${{ matrix.db }}_before_expdp.log schemas=NEXTCLOUD || true
216+
docker cp db:/opt/oracle/admin/${{ matrix.oci-name }}/dpdump/${{ matrix.db }}_before.dmp /tmp/ || true
217+
fi
218+
219+
- name: Checkout app at PR version
220+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
221+
with:
222+
path: apps/${{ env.APP_NAME }}
223+
persist-credentials: false
224+
225+
- name: Run occ upgrade
226+
run: ./occ upgrade -vvv
227+
228+
- name: Check if the PR version upgraded correctly
229+
run: |
230+
./occ status
231+
./occ app:list --output json | jq -e '.enabled | has("${{ env.APP_NAME }}")'
232+
./occ migrations:status ${{ env.APP_NAME }}
233+
234+
- name: Dump database after upgrade
235+
if: always()
236+
run: |
237+
if [ "${{ matrix.db }}" = "sqlite" ]; then
238+
cp data/nextcloud.db /tmp/${{ matrix.db }}_after.db
239+
elif [ "${{ matrix.db }}" = "pgsql" ]; then
240+
docker exec db pg_dump -U root nextcloud > /tmp/${{ matrix.db }}_after.sql
241+
elif [ "${{ matrix.db }}" = "mysql" ] || [ "${{ matrix.db }}" = "mariadb" ]; then
242+
docker exec db mariadb-dump -uroot -prootpassword nextcloud > /tmp/${{ matrix.db }}_after.sql
243+
elif [[ "${{ matrix.db }}" == oci* ]]; then
244+
docker exec db expdp system/oracle@${{ matrix.oci-name }} directory=DATA_PUMP_DIR dumpfile=${{ matrix.db }}_after.dmp logfile=${{ matrix.db }}_after_expdp.log schemas=NEXTCLOUD || true
245+
docker cp db:/opt/oracle/admin/${{ matrix.oci-name }}/dpdump/${{ matrix.db }}_after.dmp /tmp/ || true
246+
fi
247+
248+
- name: Upload artifacts
249+
uses: actions/upload-artifact@v4
250+
if: always()
251+
with:
252+
name: ${{ matrix.db }}-artifacts
253+
path: |
254+
/tmp/${{ matrix.db }}_before.*
255+
/tmp/${{ matrix.db }}_after.*
256+
data/nextcloud.log
257+
data/context_chat.log
258+
if-no-files-found: ignore
259+
260+
261+
summary:
262+
permissions:
263+
contents: none
264+
runs-on: ubuntu-latest-low
265+
needs: [changes, migration-test]
266+
267+
if: always()
268+
269+
name: migration-test-summary
270+
271+
steps:
272+
- name: Summary status
273+
run: if ${{ needs.changes.outputs.src != 'false' && needs.migration-test.result != 'success' }}; then exit 1; fi

0 commit comments

Comments
 (0)