ci: separate dev deployment, main checks and GitHub mirroring
GitHub Git mirror / mirror (push) Skipped
Development CI / check-and-package (push) Successful in 4m3s
Development CI / image (push) Successful in 28s
Development CI / deploy-development (push) Successful in 11s

This commit is contained in:
root committed 2026-10-29 21:03:01 +08:00
1 parent da4b1e3b18
commit 469af15045
20 files changed
+360 -121

No files matched your search

+26 -2
View File
@@ -204,7 +204,7 @@ class DeploymentTests(unittest.TestCase):
(self.directory / '.env').write_text(
f'RAWMARK_CHANNEL=development\nRAWMARK_PROJECT=rawmark-ci-deploy\n'
f'RAWMARK_BIND=127.0.0.1\nRAWMARK_PORT=21899\nRAWMARK_DATA_DIR={self.directory}/data\n')
self.image = release.GITEA_IMAGE + '@' + DIGEST
self.image = release.GITEA_DEV_IMAGE + '@' + DIGEST
self.previous = {'Id': 'old-id', 'Image': 'old-image', 'State': {'Running': True},
'Mounts': [{'Destination': '/data', 'Type': 'bind', 'Source': str(self.directory / 'data')}]}
self.image_info = {'Id': 'new-image', 'Config': {'User': '65532:65532', 'Labels': {
@@ -249,7 +249,7 @@ class DeploymentTests(unittest.TestCase):
deploy.deployment(self.directory, 'development', self.image, SHA, '0.1.1')
docker.assert_not_called()
def test_stale_main_skips_without_stopping_existing_service(self):
def test_stale_dev_skips_without_stopping_existing_service(self):
with patch.object(deploy, 'API') as api, patch.object(deploy, 'run', side_effect=self.command):
api.return_value.repo.return_value = {'commit': {'id': 'c' * 40}}
deploy.deployment(self.directory, 'development', self.image, SHA, '0.1.1')
@@ -278,6 +278,21 @@ class DeploymentTests(unittest.TestCase):
self.assertLess(stop, start)
self.assertIn('RAWMARK_IMAGE=' + self.image, (self.directory / '.env').read_text())
def test_existing_data_is_backed_up_without_a_container(self):
def without_container(*args, **kwargs):
if args[:2] == ('docker', 'ps'):
return ''
return self.command(*args, **kwargs)
opener = Mock()
opener.open.side_effect = [contextlib.nullcontext(io.BytesIO(b'<html>RawMark</html>')),
contextlib.nullcontext(io.BytesIO(b'{"code":0}'))]
with patch.object(deploy, 'run', side_effect=without_container), patch.object(
deploy.urllib.request, 'build_opener', return_value=opener):
deploy.deployment(self.directory, 'development', self.image, SHA, '0.1.1')
receipt = json.loads((self.directory / 'deployment.json').read_text())
self.assertTrue(Path(receipt['backup']).exists())
self.assertIsNone(receipt['previous_image'])
def test_failed_replacement_keeps_backup_and_does_not_downgrade_data(self):
def failure(*args, **kwargs):
if args[:2] == ('docker', 'compose') and 'up' in args:
@@ -293,6 +308,15 @@ class DeploymentTests(unittest.TestCase):
self.assertNotIn('RAWMARK_IMAGE=', (self.directory / '.env').read_text())
class DevelopmentVersionTests(unittest.TestCase):
def test_version_uses_utc_commit_date_and_exact_eight_character_hash(self):
with patch.dict(os.environ, {'RAWMARK_BUILD_CHANNEL': 'development'}), patch.object(
release, 'run', side_effect=[SHA, '0']):
self.assertEqual(release.build_version(), '19700101-aaaaaaaa')
self.assertEqual(release.archive_name('19700101-aaaaaaaa', 'linux/amd64'),
'RawMark_19700101-aaaaaaaa_linux_amd64.tar.gz')
class CleanupTests(unittest.TestCase):
def test_cleanup_rejects_broad_filter(self):
with patch('subprocess.check_output') as docker:
+36
View File
@@ -0,0 +1,36 @@
"""Verify strict mirroring with isolated local repositories."""
import os
from pathlib import Path
import subprocess
import sys
import tempfile
import unittest
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from mirror import git, references, synchronize
class MirrorTests(unittest.TestCase):
def test_full_history_tags_deletions_and_failed_source(self):
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
source, target = root / 'source', root / 'target.git'
subprocess.run(['git', 'init', '-b', 'main', str(source)], check=True, capture_output=True)
subprocess.run(['git', 'init', '--bare', str(target)], check=True, capture_output=True)
(source / 'note.md').write_text('synthetic note')
git(source, 'add', '.')
git(source, '-c', 'user.name=Test', '-c', '[email protected]', 'commit', '-m', 'test')
git(source, 'branch', 'dev')
git(source, '-c', 'user.name=Test', '-c', '[email protected]', 'tag', '-a', 'test-tag', '-m', 'test')
state = root / 'state'
synchronize(state, str(source), str(target), os.environ.copy())
self.assertEqual(references(source), references(target))
git(source, 'branch', '-D', 'dev')
git(source, 'tag', '-d', 'test-tag')
git(target, 'branch', 'target-only', 'main')
synchronize(state, str(source), str(target), os.environ.copy())
self.assertEqual(references(source), references(target))
before = references(target)
with self.assertRaises(subprocess.CalledProcessError):
synchronize(state, str(root / 'missing'), str(target), os.environ.copy())
self.assertEqual(before, references(target))