Skip to content

Commit eb6268f

Browse files
authored
ci: add Docker tests (#179)
1 parent 731e2d7 commit eb6268f

File tree

7 files changed

+354
-0
lines changed

7 files changed

+354
-0
lines changed

.github/workflows/tests.yml

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
name: Tests
2+
on:
3+
push:
4+
pull_request:
5+
#on:
6+
# push:
7+
# branches:
8+
# - main
9+
# pull_request:
10+
# branches:
11+
# - main
12+
13+
env:
14+
IMAGE_NAME: mysql-bkup
15+
16+
jobs:
17+
test:
18+
runs-on: ubuntu-latest
19+
services:
20+
mysql:
21+
image: mysql:9
22+
env:
23+
MYSQL_ROOT_PASSWORD: password
24+
MYSQL_DATABASE: testdb
25+
MYSQL_USER: user
26+
MYSQL_PASSWORD: password
27+
ports:
28+
- 3306:3306
29+
options: >-
30+
--health-cmd="mysqladmin ping -h 127.0.0.1 -uuser -ppassword"
31+
--health-interval=10s
32+
--health-timeout=5s
33+
--health-retries=5
34+
mysql8:
35+
image: mysql:8
36+
env:
37+
MYSQL_ROOT_PASSWORD: password
38+
MYSQL_DATABASE: testdb
39+
MYSQL_USER: user
40+
MYSQL_PASSWORD: password
41+
ports:
42+
- 3308:3306
43+
options: >-
44+
--health-cmd="mysqladmin ping -h 127.0.0.1 -uuser -ppassword"
45+
--health-interval=10s
46+
--health-timeout=5s
47+
--health-retries=5
48+
mysql5:
49+
image: mysql:5
50+
env:
51+
MYSQL_ROOT_PASSWORD: password
52+
MYSQL_DATABASE: testdb
53+
MYSQL_USER: user
54+
MYSQL_PASSWORD: password
55+
ports:
56+
- 3305:3306
57+
options: >-
58+
--health-cmd="mysqladmin ping -h 127.0.0.1 -uuser -ppassword"
59+
--health-interval=10s
60+
--health-timeout=5s
61+
--health-retries=5
62+
steps:
63+
- name: Checkout repository
64+
uses: actions/checkout@v4
65+
66+
- name: Set up Docker Buildx
67+
uses: docker/setup-buildx-action@v3
68+
- name: Create Minio container
69+
run: |
70+
docker run -d --rm --name minio \
71+
--network host \
72+
-p 9000:9000 \
73+
-e MINIO_ACCESS_KEY=minioadmin \
74+
-e MINIO_SECRET_KEY=minioadmin \
75+
-e MINIO_REGION_NAME="eu" \
76+
minio/minio server /data
77+
echo "Create Minio container completed"
78+
- name: Install MinIO Client (mc)
79+
run: |
80+
curl -O https://dl.min.io/client/mc/release/linux-amd64/mc
81+
chmod +x mc
82+
sudo mv mc /usr/local/bin/
83+
84+
- name: Wait for MinIO to be ready
85+
run: sleep 5
86+
87+
- name: Configure MinIO Client
88+
run: |
89+
mc alias set local http://localhost:9000 minioadmin minioadmin
90+
mc alias list
91+
92+
- name: Create MinIO Bucket
93+
run: |
94+
mc mb local/backups
95+
echo "Bucket backups created successfully."
96+
# Build the Docker image
97+
- name: Build Docker Image
98+
run: |
99+
docker buildx build --build-arg appVersion=test -t ${{ env.IMAGE_NAME }}:latest --load .
100+
101+
- name: Verify Docker images
102+
run: |
103+
docker images
104+
105+
- name: Wait for MySQL to be ready
106+
run: |
107+
docker run --rm --network host mysql:9 mysqladmin ping -h 127.0.0.1 -uuser -ppassword --wait
108+
- name: Test restore
109+
run: |
110+
docker run --rm --name ${{ env.IMAGE_NAME }} \
111+
-v ./migrations:/backup/ \
112+
--network host \
113+
-e DB_HOST=127.0.0.1 \
114+
-e DB_USERNAME=root \
115+
-e DB_PASSWORD=password \
116+
-e DB_NAME=testdb \
117+
${{ env.IMAGE_NAME }}:latest restore -f init.sql
118+
echo "Database restore completed"
119+
- name: Test restore Mysql8
120+
run: |
121+
docker run --rm --name ${{ env.IMAGE_NAME }} \
122+
-v ./migrations:/backup/ \
123+
--network host \
124+
-e DB_HOST=127.0.0.1 \
125+
-e DB_PORT=3308 \
126+
-e DB_USERNAME=root \
127+
-e DB_PASSWORD=password \
128+
-e DB_NAME=testdb \
129+
${{ env.IMAGE_NAME }}:latest restore -f init.sql
130+
echo "Test restore Mysql8 completed"
131+
- name: Test restore Mysql5
132+
run: |
133+
docker run --rm --name ${{ env.IMAGE_NAME }} \
134+
-v ./migrations:/backup/ \
135+
--network host \
136+
-e DB_HOST=127.0.0.1 \
137+
-e DB_PORT=3305 \
138+
-e DB_USERNAME=root \
139+
-e DB_PASSWORD=password \
140+
-e DB_NAME=testdb \
141+
${{ env.IMAGE_NAME }}:latest restore -f init.sql
142+
echo "Test restore Mysql5 completed"
143+
- name: Test backup
144+
run: |
145+
docker run --rm --name ${{ env.IMAGE_NAME }} \
146+
-v ./migrations:/backup/ \
147+
--network host \
148+
-e DB_HOST=127.0.0.1 \
149+
-e DB_USERNAME=user \
150+
-e DB_PASSWORD=password \
151+
-e DB_NAME=testdb \
152+
${{ env.IMAGE_NAME }}:latest backup
153+
echo "Database backup completed"
154+
- name: Test backup Mysql8
155+
run: |
156+
docker run --rm --name ${{ env.IMAGE_NAME }} \
157+
-v ./migrations:/backup/ \
158+
--network host \
159+
-e DB_PORT=3308 \
160+
-e DB_HOST=127.0.0.1 \
161+
-e DB_USERNAME=user \
162+
-e DB_PASSWORD=password \
163+
-e DB_NAME=testdb \
164+
${{ env.IMAGE_NAME }}:latest backup
165+
echo "Test backup Mysql8 completed"
166+
- name: Test backup Mysql5
167+
run: |
168+
docker run --rm --name ${{ env.IMAGE_NAME }} \
169+
-v ./migrations:/backup/ \
170+
--network host \
171+
-e DB_PORT=3305 \
172+
-e DB_HOST=127.0.0.1 \
173+
-e DB_USERNAME=user \
174+
-e DB_PASSWORD=password \
175+
-e DB_NAME=testdb \
176+
${{ env.IMAGE_NAME }}:latest backup
177+
echo "Test backup Mysql5 completed"
178+
- name: Test encrypted backup
179+
run: |
180+
docker run --rm --name ${{ env.IMAGE_NAME }} \
181+
-v ./migrations:/backup/ \
182+
--network host \
183+
-e DB_HOST=127.0.0.1 \
184+
-e DB_USERNAME=user \
185+
-e DB_PASSWORD=password \
186+
-e GPG_PASSPHRASE=password \
187+
-e DB_NAME=testdb \
188+
${{ env.IMAGE_NAME }}:latest backup --disable-compression --custom-name encrypted-bkup
189+
echo "Database encrypted backup completed"
190+
- name: Test restore encrypted backup | testdb -> testdb2
191+
run: |
192+
docker run --rm --name ${{ env.IMAGE_NAME }} \
193+
-v ./migrations:/backup/ \
194+
--network host \
195+
-e DB_HOST=127.0.0.1 \
196+
-e DB_USERNAME=root \
197+
-e DB_PASSWORD=password \
198+
-e GPG_PASSPHRASE=password \
199+
-e DB_NAME=testdb2 \
200+
${{ env.IMAGE_NAME }}:latest restore -f /backup/encrypted-bkup.sql.gpg
201+
echo "Test restore encrypted backup completed"
202+
- name: Test migrate database testdb -> testdb3
203+
run: |
204+
docker run --rm --name ${{ env.IMAGE_NAME }} \
205+
-v ./migrations:/backup/ \
206+
--network host \
207+
-e DB_HOST=127.0.0.1 \
208+
-e DB_USERNAME=root \
209+
-e DB_PASSWORD=password \
210+
-e GPG_PASSPHRASE=password \
211+
-e DB_NAME=testdb \
212+
-e TARGET_DB_HOST=127.0.0.1 \
213+
-e TARGET_DB_PORT=3306 \
214+
-e TARGET_DB_NAME=testdb3 \
215+
-e TARGET_DB_USERNAME=root \
216+
-e TARGET_DB_PASSWORD=password \
217+
${{ env.IMAGE_NAME }}:latest migrate
218+
echo "Test migrate database testdb -> testdb3 completed"
219+
- name: Test backup all databases
220+
run: |
221+
docker run --rm --name ${{ env.IMAGE_NAME }} \
222+
-v ./migrations:/backup/ \
223+
--network host \
224+
-e DB_HOST=127.0.0.1 \
225+
-e DB_USERNAME=root \
226+
-e DB_PASSWORD=password \
227+
-e DB_NAME=testdb \
228+
${{ env.IMAGE_NAME }}:latest backup --all-databases
229+
echo "Database backup completed"
230+
- name: Test multiple backup
231+
run: |
232+
docker run --rm --name ${{ env.IMAGE_NAME }} \
233+
-v ./migrations:/backup/ \
234+
--network host \
235+
-e DB_HOST=127.0.0.1 \
236+
-e TESTDB2_DB_USERNAME=root \
237+
-e TESTDB2_DB_PASSWORD=password \
238+
-e TESTDB2_DB_HOST=127.0.0.1 \
239+
${{ env.IMAGE_NAME }}:latest backup -c /backup/test_config.yaml
240+
echo "Database backup completed"
241+
- name: Test backup Minio (s3)
242+
run: |
243+
docker run --rm --name ${{ env.IMAGE_NAME }} \
244+
--network host \
245+
-e DB_HOST=127.0.0.1 \
246+
-e DB_USERNAME=user \
247+
-e DB_PASSWORD=password \
248+
-e DB_NAME=testdb \
249+
-e AWS_S3_ENDPOINT="http://127.0.0.1:9000" \
250+
-e AWS_S3_BUCKET_NAME=backups \
251+
-e AWS_ACCESS_KEY=minioadmin \
252+
-e AWS_SECRET_KEY=minioadmin \
253+
-e AWS_DISABLE_SSL="true" \
254+
-e AWS_REGION="eu" \
255+
-e AWS_FORCE_PATH_STYLE="true" ${{ env.IMAGE_NAME }}:latest backup -s s3 --custom-name minio-backup
256+
echo "Test backup Minio (s3) completed"
257+
- name: Test restore Minio (s3)
258+
run: |
259+
docker run --rm --name ${{ env.IMAGE_NAME }} \
260+
--network host \
261+
-e DB_HOST=127.0.0.1 \
262+
-e DB_USERNAME=user \
263+
-e DB_PASSWORD=password \
264+
-e DB_NAME=testdb \
265+
-e AWS_S3_ENDPOINT="http://127.0.0.1:9000" \
266+
-e AWS_S3_BUCKET_NAME=backups \
267+
-e AWS_ACCESS_KEY=minioadmin \
268+
-e AWS_SECRET_KEY=minioadmin \
269+
-e AWS_DISABLE_SSL="true" \
270+
-e AWS_REGION="eu" \
271+
-e AWS_FORCE_PATH_STYLE="true" ${{ env.IMAGE_NAME }}:latest restore -s s3 -f minio-backup.sql.gz
272+
echo "Test backup Minio (s3) completed"
273+
- name: Test scheduled backup
274+
run: |
275+
docker run -d --rm --name ${{ env.IMAGE_NAME }} \
276+
-v ./migrations:/backup/ \
277+
--network host \
278+
-e DB_HOST=127.0.0.1 \
279+
-e DB_USERNAME=user \
280+
-e DB_PASSWORD=password \
281+
-e DB_NAME=testdb \
282+
${{ env.IMAGE_NAME }}:latest backup -e "@every 10s"
283+
284+
echo "Waiting for backup to be done..."
285+
sleep 25
286+
docker logs ${{ env.IMAGE_NAME }}
287+
echo "Test scheduled backup completed"
288+
# Cleanup: Stop and remove containers
289+
- name: Clean up
290+
run: |
291+
docker stop ${{ env.IMAGE_NAME }} || true
292+
docker rm ${{ env.IMAGE_NAME }} || true

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
**MYSQL-BKUP** is a Docker container image designed to **backup, restore, and migrate MySQL databases**.
44
It supports a variety of storage options and ensures data security through GPG encryption.
55

6+
[![Tests](https://github.com/jkaninda/mysql-bkup/actions/workflows/tests.yml/badge.svg)](https://github.com/jkaninda/mysql-bkup/actions/workflows/tests.yml)
67
[![Build](https://github.com/jkaninda/mysql-bkup/actions/workflows/release.yml/badge.svg)](https://github.com/jkaninda/mysql-bkup/actions/workflows/release.yml)
78
[![Go Report](https://goreportcard.com/badge/github.com/jkaninda/mysql-bkup)](https://goreportcard.com/report/github.com/jkaninda/mysql-bkup)
89
![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/jkaninda/mysql-bkup?style=flat-square)

cmd/backup.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,6 @@ func init() {
5252
BackupCmd.PersistentFlags().BoolP("disable-compression", "", false, "Disable backup compression")
5353
BackupCmd.PersistentFlags().BoolP("all-databases", "a", false, "Backup all databases")
5454
BackupCmd.PersistentFlags().BoolP("all-in-one", "A", false, "Backup all databases in a single file")
55+
BackupCmd.PersistentFlags().StringP("custom-name", "", "", "Custom backup name")
5556

5657
}

migrations/init.sql

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
-- Create the database testdb2 and testdb3
2+
CREATE DATABASE IF NOT EXISTS testdb2;
3+
CREATE DATABASE IF NOT EXISTS testdb3;
4+
CREATE DATABASE IF NOT EXISTS fakedb;
5+
USE testdb;
6+
7+
-- Create the 'users' table
8+
CREATE TABLE users (
9+
id INT AUTO_INCREMENT PRIMARY KEY,
10+
name VARCHAR(100) NOT NULL,
11+
email VARCHAR(100) NOT NULL UNIQUE,
12+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
13+
);
14+
15+
-- Create the 'orders' table
16+
CREATE TABLE orders (
17+
id INT AUTO_INCREMENT PRIMARY KEY,
18+
user_id INT NOT NULL,
19+
amount DECIMAL(10,2) NOT NULL,
20+
status ENUM('pending', 'completed', 'canceled') NOT NULL DEFAULT 'pending',
21+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
22+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
23+
);
24+
25+
-- Insert fake users
26+
INSERT INTO users (name, email) VALUES
27+
('Alice Smith', 'alice@example.com'),
28+
('Bob Johnson', 'bob@example.com'),
29+
('Charlie Brown', 'charlie@example.com');
30+
31+
-- Insert fake orders
32+
INSERT INTO orders (user_id, amount, status) VALUES
33+
(1, 100.50, 'completed'),
34+
(2, 200.75, 'pending'),
35+
(3, 50.00, 'canceled');

migrations/test_config.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#cronExpression: "@every 20s"
2+
#backupRescueMode: false
3+
databases:
4+
- host: 127.0.0.1
5+
port: 3306
6+
name: testdb
7+
user: user
8+
password: password
9+
- name: testdb2
10+
# database credentials from environment variables
11+
#TESTDB2_DB_USERNAME
12+
#TESTDB2_DB_PASSWORD
13+
#TESTDB2_DB_HOST

pkg/backup.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func StartBackup(cmd *cobra.Command) {
5151
if err != nil {
5252
dbConf = initDbConfig(cmd)
5353
if config.cronExpression == "" {
54+
config.allowCustomName = true
5455
createBackupTask(dbConf, config)
5556
} else {
5657
if utils.IsValidCronExpression(config.cronExpression) {
@@ -145,11 +146,18 @@ func backupTask(db *dbConfig, config *BackupConfig) {
145146
if config.all && config.allInOne {
146147
prefix = "all_databases"
147148
}
149+
148150
// Generate file name
149151
backupFileName := fmt.Sprintf("%s_%s.sql.gz", prefix, time.Now().Format("20060102_150405"))
150152
if config.disableCompression {
151153
backupFileName = fmt.Sprintf("%s_%s.sql", prefix, time.Now().Format("20060102_150405"))
152154
}
155+
if config.customName != "" && config.allowCustomName && !config.all {
156+
backupFileName = fmt.Sprintf("%s.sql.gz", config.customName)
157+
if config.disableCompression {
158+
backupFileName = fmt.Sprintf("%s.sql", config.customName)
159+
}
160+
}
153161
config.backupFileName = backupFileName
154162
s := strings.ToLower(config.storage)
155163
switch s {

0 commit comments

Comments
 (0)