├── .editorconfig ├── .flake8 ├── .github └── workflows │ ├── build-test.yml │ └── codeql-analysis.yml ├── .gitignore ├── .mypy.ini ├── COPYING ├── README.md ├── autoformat.sh ├── contrib ├── base-config.toml.sample ├── npmdeps │ ├── .gitignore │ ├── fetch_npm.py │ └── package.json └── test-archive-config.toml ├── data ├── 3rd-party.toml ├── archive-sections.json ├── laniakea-lighthouse.service.in ├── laniakea-mailgun.service.in ├── laniakea-mirk.service.in ├── laniakea-scheduler.service.in ├── laniakea-webdash.service.in ├── laniakea-webswview.service.in ├── laniakea-webupload.service.in ├── lintian.toml ├── meson.build └── words │ ├── adjectives.txt │ ├── animals.txt │ ├── intermediate.txt │ └── nouns.txt ├── docs ├── .readthedocs.yaml ├── Makefile ├── _graphics │ ├── laniakea-overview.svg │ ├── lk-adaptors.svg │ ├── lk-tools.svg │ ├── lk-usertools.svg │ ├── lk-workers.svg │ └── logo.svg ├── api │ ├── index.rst │ ├── laniakea.db.rst │ ├── laniakea.msgstream.rst │ ├── laniakea.rst │ └── laniakea.utils.rst ├── conf.py ├── design-principles.rst ├── general │ ├── datasync.rst │ ├── index.rst │ ├── initial-setup.rst │ ├── lighthouse.rst │ ├── rubicon.rst │ ├── tools │ │ ├── index.rst │ │ ├── lk-admin.rst │ │ └── lk-keytool.rst │ └── worker-setup.rst ├── index.rst ├── meson.build ├── modules │ ├── debcheck.rst │ ├── index.rst │ ├── isotope.rst │ ├── planter.rst │ ├── spears.rst │ └── synchrotron.rst ├── porting-status.md ├── readthedocs-reqs.txt ├── requirements.txt └── web │ └── index.rst ├── meson.build ├── meson_options.txt ├── pyproject.toml ├── pyreqcheck.py ├── requirements.base.txt ├── requirements.matrix.txt ├── requirements.tests.txt ├── requirements.txt ├── requirements.web.txt ├── src ├── debcheck │ ├── __init__.py │ ├── cli.py │ ├── debcheck │ ├── dose.py │ └── meson.build ├── keytool │ ├── keytool.py │ └── meson.build ├── laniakea │ ├── __init__.py │ ├── alembic.ini │ ├── alembic │ │ ├── env.py │ │ ├── script.py.mako │ │ └── versions │ │ │ └── 34ccc7e6f9b8_baseline.py │ ├── archive │ │ ├── __init__.py │ │ ├── appstream.py │ │ ├── changes.py │ │ ├── manage.py │ │ ├── pkgimport.py │ │ ├── uploadermgr.py │ │ └── utils.py │ ├── ariadne │ │ ├── __init__.py │ │ ├── maintenance.py │ │ └── package_jobs.py │ ├── db │ │ ├── __init__.py │ │ ├── archive.py │ │ ├── base.py │ │ ├── core.py │ │ ├── debcheck.py │ │ ├── flatpak.py │ │ ├── isotope.py │ │ ├── jobs.py │ │ ├── spears.py │ │ ├── stats.py │ │ ├── synchrotron.py │ │ └── workers.py │ ├── dud.py │ ├── flatpak_util.py │ ├── git.py │ ├── localconfig.py │ ├── logging.py │ ├── meson.build │ ├── msgstream │ │ ├── __init__.py │ │ ├── event_msg.py │ │ ├── signedjson.py │ │ └── signing.py │ ├── reporeader.py │ ├── typing.py │ ├── userhints.py │ └── utils │ │ ├── __init__.py │ │ ├── arches.py │ │ ├── base64.py │ │ ├── command.py │ │ ├── deb822.py │ │ ├── fileutil.py │ │ ├── gpg.py │ │ ├── json.py │ │ ├── misc.py │ │ ├── renameat2.py │ │ └── traceback.py ├── lighthouse │ ├── __init__.py │ ├── cli.py │ ├── events_publisher.py │ ├── events_receiver.py │ ├── jobs_server.py │ ├── jobs_worker.py │ ├── lighthouse-server │ └── meson.build ├── lkadmin │ ├── __init__.py │ ├── archive.py │ ├── ariadne.py │ ├── cli.py │ ├── core.py │ ├── flatpak.py │ ├── isotope.py │ ├── job.py │ ├── lk-admin.py │ ├── meson.build │ ├── planter.py │ ├── spears.py │ ├── synchrotron.py │ └── utils.py ├── lkarchive │ ├── __init__.py │ ├── ariadne.py │ ├── check_dep11.py │ ├── cli.py │ ├── data_import.py │ ├── lk-archive.py │ ├── manage_pkg.py │ ├── meson.build │ ├── process_new.py │ ├── publish.py │ └── validate.py ├── lkscheduler │ ├── __init__.py │ ├── cli.py │ ├── config.py │ ├── laniakea-scheduler │ ├── meson.build │ ├── sdaemon.py │ └── statscollector.py ├── mailgun │ ├── __init__.py │ ├── cli.py │ ├── config.py │ ├── laniakea-mailgun │ ├── mailrelay.py │ ├── mailutils.py │ ├── meson.build │ └── templates │ │ ├── package-accepted-announce.tmpl │ │ ├── package-accepted.tmpl │ │ ├── package-new.tmpl │ │ └── package-rejected.tmpl ├── meson.build ├── mirk │ ├── __init__.py │ ├── cli.py │ ├── config.py │ ├── matrix_client.py │ ├── meson.build │ ├── messages.py │ ├── mirk │ └── msgpublish.py ├── planter │ ├── meson.build │ └── planter.py ├── rubicon │ ├── __init__.py │ ├── cli.py │ ├── fileimport.py │ ├── import_isotope.py │ ├── import_package.py │ ├── meson.build │ ├── rubicon │ ├── rubicon.in │ └── rubiconfig.py ├── spears │ ├── __init__.py │ ├── britney.py │ ├── britneyconfig.py │ ├── cli.py │ ├── excuses.py │ ├── meson.build │ ├── spears │ └── spearsengine.py ├── synchrotron │ ├── __init__.py │ ├── cli.py │ ├── meson.build │ ├── syncengine.py │ └── synchrotron ├── webdash │ ├── lkweb │ │ ├── __init__.py │ │ ├── api │ │ │ ├── __init__.py │ │ │ └── api.py │ │ ├── app.py │ │ ├── config.py │ │ ├── decorators.py │ │ ├── depcheck │ │ │ ├── __init__.py │ │ │ └── views.py │ │ ├── extensions.py │ │ ├── jobs │ │ │ ├── __init__.py │ │ │ └── views.py │ │ ├── migrations │ │ │ ├── __init__.py │ │ │ └── views.py │ │ ├── osimages │ │ │ ├── __init__.py │ │ │ └── views.py │ │ ├── overview │ │ │ ├── __init__.py │ │ │ └── views.py │ │ ├── review_queues │ │ │ ├── __init__.py │ │ │ └── views.py │ │ ├── synchronization │ │ │ ├── __init__.py │ │ │ └── views.py │ │ └── utils.py │ ├── lkwebdash.ini.in │ ├── meson.build │ ├── run-devel.sh │ ├── templates │ │ └── default │ │ │ ├── .gitignore │ │ │ ├── depcheck │ │ │ ├── index.html │ │ │ ├── issue.html │ │ │ ├── issues_list.html │ │ │ └── layout.html │ │ │ ├── errors │ │ │ ├── 404.html │ │ │ └── 500.html │ │ │ ├── index.html │ │ │ ├── jobs │ │ │ ├── job_generic.html │ │ │ ├── job_osimage.html │ │ │ ├── job_pkgbuild.html │ │ │ ├── logviewer.html │ │ │ ├── queue.html │ │ │ ├── queue_stats.html │ │ │ └── workers.html │ │ │ ├── layouts │ │ │ └── base.html │ │ │ ├── migrations │ │ │ ├── excuse.html │ │ │ ├── excuses.html │ │ │ ├── index.html │ │ │ └── layout.html │ │ │ ├── osimages │ │ │ └── index.html │ │ │ ├── review_queues │ │ │ └── index.html │ │ │ ├── static │ │ │ ├── css │ │ │ │ └── laniakea.css │ │ │ └── js │ │ │ │ ├── laniakea.js │ │ │ │ └── term2html.js │ │ │ └── synchronization │ │ │ ├── blacklist.html │ │ │ ├── index.html │ │ │ └── sync_issue_table.html │ └── wsgi.py ├── webswview │ ├── lkswview │ │ ├── __init__.py │ │ ├── api │ │ │ ├── __init__.py │ │ │ └── api.py │ │ ├── app.py │ │ ├── config.py │ │ ├── decorators.py │ │ ├── extensions.py │ │ ├── packages │ │ │ ├── __init__.py │ │ │ └── views.py │ │ ├── portal │ │ │ ├── __init__.py │ │ │ └── views.py │ │ ├── software │ │ │ ├── __init__.py │ │ │ └── views.py │ │ └── utils.py │ ├── lkwebswview.ini.in │ ├── meson.build │ ├── run-devel.sh │ ├── templates │ │ ├── default │ │ │ ├── .gitignore │ │ │ ├── categories_index.html │ │ │ ├── category_view.html │ │ │ ├── errors │ │ │ │ ├── 404.html │ │ │ │ └── 500.html │ │ │ ├── index.html │ │ │ ├── layouts │ │ │ │ └── base.html │ │ │ ├── packages │ │ │ │ ├── bin_details.html │ │ │ │ ├── build_details.html │ │ │ │ ├── builds_list.html │ │ │ │ ├── excuse_details.html │ │ │ │ └── src_details.html │ │ │ ├── pkg_search_results.html │ │ │ ├── repo_index.html │ │ │ ├── section_view.html │ │ │ ├── sections_index.html │ │ │ ├── software │ │ │ │ └── sw_details.html │ │ │ ├── software_search_results.html │ │ │ └── static │ │ │ │ ├── css │ │ │ │ └── laniakea_swview.css │ │ │ │ └── img │ │ │ │ ├── app-icon.svg │ │ │ │ ├── brand.svg │ │ │ │ ├── categories │ │ │ │ ├── LICENSE.Breeze │ │ │ │ ├── applications-development.svg │ │ │ │ ├── applications-education.svg │ │ │ │ ├── applications-games.svg │ │ │ │ ├── applications-graphics.svg │ │ │ │ ├── applications-internet.svg │ │ │ │ ├── applications-multimedia.svg │ │ │ │ ├── applications-office.svg │ │ │ │ ├── applications-science.svg │ │ │ │ └── applications-utilities.svg │ │ │ │ └── logo.svg │ │ └── pureos │ │ │ ├── .gitignore │ │ │ ├── index.html │ │ │ ├── layouts │ │ │ └── base.html │ │ │ └── static │ │ │ ├── css │ │ │ └── laniakea_swview.css │ │ │ └── img │ │ │ ├── app-icon.svg │ │ │ ├── apps-on-device.png │ │ │ ├── brand.svg │ │ │ ├── categories │ │ │ ├── applications-development.svg │ │ │ ├── applications-education.svg │ │ │ ├── applications-games.svg │ │ │ ├── applications-graphics.svg │ │ │ ├── applications-internet.svg │ │ │ ├── applications-multimedia.svg │ │ │ ├── applications-office.svg │ │ │ ├── applications-science.svg │ │ │ └── applications-utilities.svg │ │ │ └── logo.svg │ └── wsgi.py └── webupload │ ├── lkwebupload.ini │ ├── lkwebupload │ ├── __init__.py │ ├── app.py │ ├── config.py │ └── upload │ │ ├── __init__.py │ │ └── views.py │ ├── meson.build │ ├── run-devel.sh │ └── wsgi.py └── tests ├── __init__.py ├── ci ├── Dockerfile-debian-stable ├── Dockerfile-debian-testing ├── README.md ├── containers.conf ├── install-native-deps.sh ├── make-documentation.py ├── run-lint.sh ├── run-tests.sh ├── run-venv-prepare.sh └── storage.conf ├── conftest.py ├── containers └── postgres │ └── Dockerfile ├── meson.build ├── plugins └── pytest_podman │ ├── LICENSE.txt │ ├── __init__.py │ └── plugin.py ├── podman-compose.yml ├── test_archive.py ├── test_data ├── changes │ ├── 1.changes │ ├── 2.changes │ ├── bogus-post.changes │ ├── bogus-pre.changes │ └── valid.changes ├── config │ ├── archive-config.toml │ └── base-config.toml ├── dep11 │ ├── CID-Index-amd64.json.xz │ ├── Components-amd64.yml.xz │ ├── fetch-appstream.sh │ └── icons-64x64.tar.gz ├── gpg │ ├── BrokenSigFile.txt │ ├── NotSignedFile.txt │ ├── SignedFile.txt │ ├── keyrings │ │ ├── keyring.gpg │ │ └── other-keyring.gpg │ └── secret-home │ │ ├── .gpg-v21-migrated │ │ ├── private-keys-v1.d │ │ └── 37E2C55C7C93586DA424642111539C2F4952141D.key │ │ ├── pubring.gpg │ │ ├── secring.gpg │ │ └── trustdb.gpg ├── packages │ ├── .gitignore │ ├── Makefile │ ├── create_keys │ ├── gpg │ │ ├── .gpg-v21-migrated │ │ ├── gpg.conf │ │ ├── openpgp-revocs.d │ │ │ ├── 22865D3DA7CF3DE67C1AF9A74014AB2D03010AA9.rev │ │ │ └── 589E8FA542378066E944B6222F7C63E8F3A2C549.rev │ │ ├── private-keys-v1.d │ │ │ ├── 0455C3AF7F36C15A0C6A7B0638D52E313663C0BD.key │ │ │ ├── 472886E308A3F53B1BB34917FAE6B0D696ED9A0A.key │ │ │ ├── 8CB0C561CAB10EEF594CBB5835161A5E5A76A1DA.key │ │ │ ├── A0405CB8F782F995AB5912C7D42AB38FE9EA7F50.key │ │ │ ├── AD0058FBD72B80D255ACB344431BF5A7D5B204C6.key │ │ │ └── EB9EC8B0681FEAA9FA56AEF4B68DD0D15DE0384F.key │ │ ├── pubkey_amaintainer.gpg │ │ ├── pubkey_developpeur.gpg │ │ ├── pubkey_snowman.gpg │ │ ├── pubring.gpg │ │ ├── random_seed │ │ ├── secring.gpg │ │ └── trustdb.gpg │ ├── grave-0.1 │ │ ├── debian │ │ │ ├── README.source │ │ │ ├── changelog │ │ │ ├── control │ │ │ ├── copyright │ │ │ ├── grave.install │ │ │ └── rules │ │ └── some-file │ ├── linux-42.0 │ │ ├── debian │ │ │ ├── changelog │ │ │ ├── control │ │ │ ├── linux-image-all-signed-template.install │ │ │ ├── linux-image-all.install │ │ │ ├── rules │ │ │ └── source │ │ │ │ └── format │ │ ├── modules │ │ │ └── example.ko │ │ └── template │ │ │ └── README │ ├── nonfree-package-0.1 │ │ ├── debian │ │ │ ├── changelog │ │ │ ├── control │ │ │ ├── nonfree-package.install │ │ │ └── rules │ │ └── some-file │ ├── overlays │ │ ├── binnmu-0.1+b1 │ │ │ └── debian │ │ │ │ └── changelog │ │ ├── binnmu-0.1 │ │ │ └── debian │ │ │ │ └── changelog │ │ ├── binnmu-0.2 │ │ │ └── debian │ │ │ │ └── changelog │ │ ├── binnmu │ │ │ ├── debian │ │ │ │ ├── binnmupkg.install │ │ │ │ ├── control │ │ │ │ └── rules │ │ │ └── some-file │ │ ├── main-contrib-with-debug-0.1 │ │ │ └── debian │ │ │ │ └── changelog │ │ ├── main-contrib-with-debug-0.2 │ │ │ └── debian │ │ │ │ └── changelog │ │ ├── main-contrib-with-debug │ │ │ ├── Makefile │ │ │ ├── debian │ │ │ │ ├── contrib-with-debug.install │ │ │ │ ├── control │ │ │ │ ├── main-package.install │ │ │ │ └── rules │ │ │ ├── some-file │ │ │ └── test.c │ │ ├── package-0.1 │ │ │ └── debian │ │ │ │ └── changelog │ │ ├── package-0.2 │ │ │ └── debian │ │ │ │ └── changelog │ │ ├── package │ │ │ ├── debian │ │ │ │ ├── control │ │ │ │ ├── package.install │ │ │ │ └── rules │ │ │ └── some-file │ │ ├── pkgnew-0.1 │ │ │ └── debian │ │ │ │ ├── changelog │ │ │ │ └── control │ │ ├── pkgnew-0.2 │ │ │ └── debian │ │ │ │ ├── changelog │ │ │ │ └── control │ │ ├── pkgnew-0.2~exp │ │ │ └── debian │ │ │ │ ├── changelog │ │ │ │ └── control │ │ ├── pkgnew-0.3 │ │ │ └── debian │ │ │ │ ├── changelog │ │ │ │ └── control │ │ └── pkgnew │ │ │ ├── debian │ │ │ └── rules │ │ │ └── some-file │ ├── package-built-using-0.1 │ │ ├── debian │ │ │ ├── changelog │ │ │ ├── control │ │ │ ├── package-built-using.install │ │ │ └── rules │ │ └── some-file │ └── snowman-0.1 │ │ ├── debian │ │ ├── README.source │ │ ├── changelog │ │ ├── control │ │ ├── copyright │ │ ├── rules │ │ └── snowman.install │ │ └── some-file ├── samplerepo │ └── dummy │ │ └── dists │ │ ├── testing │ │ ├── InRelease │ │ └── main │ │ │ ├── binary-all │ │ │ └── Packages.xz │ │ │ ├── binary-amd64 │ │ │ └── Packages.xz │ │ │ └── source │ │ │ └── Sources.xz │ │ └── unstable └── spears │ ├── HeidiResult │ ├── excuses.yml │ ├── heidi-current │ └── output.txt ├── test_flatpakrepo.py ├── test_lighthouse_jobs.py ├── test_lighthouse_msgstream.py ├── test_reporeader.py ├── test_signedjson.py └── test_utils.py /.editorconfig: -------------------------------------------------------------------------------- 1 | # See https://editorconfig.org/ 2 | root = true 3 | 4 | [*] 5 | end_of_line = lf 6 | trim_trailing_whitespace = true 7 | charset = utf-8 8 | 9 | [*.sh] 10 | indent_style = space 11 | indent_size = 4 12 | 13 | [meson.build] 14 | indent_style = space 15 | indent_size = 4 16 | 17 | [*.{yml,yaml}] 18 | indent_style = space 19 | indent_size = 2 20 | 21 | [*.xml] 22 | indent_style = space 23 | indent_size = 2 24 | 25 | [*.toml] 26 | indent_style = space 27 | indent_size = 4 28 | 29 | [*.py] 30 | indent_style = space 31 | indent_size = 4 32 | 33 | [*.html] 34 | indent_style = space 35 | indent_size = 2 36 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 140 3 | ignore = E402 4 | exclude = 5 | .git, 6 | __pycache__, 7 | build, 8 | dist 9 | extend-ignore = 10 | W503, 11 | # See https://github.com/PyCQA/pycodestyle/issues/373 12 | E203, 13 | -------------------------------------------------------------------------------- /.github/workflows/build-test.yml: -------------------------------------------------------------------------------- 1 | name: Build Test 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | linters-deb-testing: 11 | name: Static Checks (Debian Testing) 12 | runs-on: ubuntu-24.04 13 | 14 | steps: 15 | - uses: actions/checkout@v3 16 | 17 | - name: Create Native Environment 18 | run: cd tests/ci/ && podman build -t laniakea -f ./Dockerfile-debian-testing . 19 | 20 | - name: Set up Python virtual environment 21 | run: podman run -a stdout -a stderr -v `pwd`:/build laniakea 22 | ./tests/ci/run-venv-prepare.sh lint-only 23 | 24 | - name: Check 25 | # FIXME: Ignore any failures for now until we have ported to SQLAlchemy >= 2.0 26 | continue-on-error: true 27 | run: podman run -a stdout -a stderr -v `pwd`:/build laniakea 28 | ./tests/ci/run-lint.sh 29 | 30 | 31 | test-deb-bullseye: 32 | name: Testsuite (Debian 12) 33 | runs-on: ubuntu-24.04 34 | 35 | steps: 36 | - uses: actions/checkout@v3 37 | 38 | - name: Create Native Environment 39 | run: cd tests/ci/ && podman build -t laniakea -f ./Dockerfile-debian-stable . 40 | 41 | - name: Set up Python virtual environment 42 | run: podman run -a stdout -a stderr -v `pwd`:/build laniakea 43 | ./tests/ci/run-venv-prepare.sh 44 | 45 | - name: Testsuite 46 | run: podman run --privileged -a stdout -a stderr --security-opt seccomp=unconfined -v `pwd`:/build laniakea 47 | ./tests/ci/run-tests.sh 48 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | schedule: 9 | - cron: '20 23 * * 6' 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | 16 | strategy: 17 | fail-fast: false 18 | matrix: 19 | language: [ 'python', 'javascript' ] 20 | 21 | steps: 22 | - name: Checkout repository 23 | uses: actions/checkout@v3 24 | 25 | - name: Initialize CodeQL 26 | uses: github/codeql-action/init@v1 27 | with: 28 | setup-python-dependencies: false 29 | languages: ${{ matrix.language }} 30 | 31 | - name: Perform CodeQL Analysis 32 | uses: github/codeql-action/analyze@v1 33 | -------------------------------------------------------------------------------- /.mypy.ini: -------------------------------------------------------------------------------- 1 | [mypy] 2 | show_column_numbers = True 3 | pretty = True 4 | 5 | strict_optional = False 6 | ignore_missing_imports = True 7 | 8 | warn_redundant_casts = True 9 | warn_unused_ignores = True 10 | -------------------------------------------------------------------------------- /autoformat.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | BASEDIR=$(dirname "$0") 5 | cd $BASEDIR 6 | 7 | echo "=== ISort ===" 8 | python -m isort . 9 | 10 | echo "=== Black ===" 11 | python -m black . 12 | -------------------------------------------------------------------------------- /contrib/base-config.toml.sample: -------------------------------------------------------------------------------- 1 | # A workspace directory where Laniakea modules will store all 2 | # their state. Should be on persistent storage. 3 | Workspace = "/tmp/test-lkws/" 4 | 5 | 6 | # Archive details, only "path" is essential 7 | [Archive] 8 | # Directory where the distribution's repository is located locally, 9 | # e.g. /srv/repo/pureos/ 10 | master_repo_name = "pureos" 11 | path = "???" 12 | 13 | 14 | # Database details 15 | [Database] 16 | db = "laniakea" 17 | user = "lkdbuser_master" 18 | password = "notReallySecret" 19 | 20 | 21 | [Synchrotron] 22 | # Keys of other distributions that Synchrotron will trust 23 | # when fetching packages from them. 24 | SourceKeyringDir = "/etc/apt/trusted.gpg.d/" 25 | 26 | 27 | # Endpoints at which a Lighthouse server should listen for job requests, 28 | # event submissions and where it should publish events. 29 | [Lighthouse.endpoints] 30 | jobs = [ "tcp://*:5570",] 31 | submit = [ "tcp://*:5571",] 32 | publish = [ "tcp://*:5572",] 33 | 34 | 35 | # Lighthouse servers that Laniakea modules should connect to in order to 36 | # submit events, request jobs, or listen to the event stream published by 37 | # a Lighthouse server. 38 | [Lighthouse.servers] 39 | jobs = [ "tcp://localhost:5570",] 40 | submit = [ "tcp://localhost:5571",] 41 | publish = [ "tcp://localhost:5572",] 42 | -------------------------------------------------------------------------------- /contrib/npmdeps/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | *.log 3 | -------------------------------------------------------------------------------- /contrib/npmdeps/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "flat": true, 3 | "dependencies": { 4 | "@fontsource/cantarell": ">=4.2.2", 5 | "@fortawesome/fontawesome-free": ">=5.8", 6 | "bulma": ">=0.9.2", 7 | "chart.js": ">=4.3.0", 8 | "chartjs-adapter-moment": ">=1.0.1", 9 | "jquery": ">=3.3.1", 10 | "moment": ">=2.29.4" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /contrib/test-archive-config.toml: -------------------------------------------------------------------------------- 1 | [[Repositories]] 2 | name = "master" 3 | origin = "ACME Inc." 4 | 5 | [[Components]] 6 | name = "main" 7 | summary = "Supported Packages" 8 | 9 | [[Architectures]] 10 | name = "amd64" 11 | summary = "AMD x86-64 architecture" 12 | 13 | [[Architectures]] 14 | name = "arm64" 15 | summary = "64-Bit ARM" 16 | 17 | [[Uploaders]] 18 | repo_name = "master" 19 | email = "testuser@example.org" 20 | fingerprints = ["DEADBEEF"] 21 | is_human = true 22 | 23 | [[Suites]] 24 | name = "unstable" 25 | alias = "" 26 | summary = "Development Suite" 27 | version = "2.0" 28 | arch_names = ["amd64", "arm64"] 29 | component_names = ["main"] 30 | 31 | [[Suites]] 32 | name = "stable" 33 | alias = "" 34 | summary = "Stable 1.0 Release" 35 | version = "1.0" 36 | arch_names = ["amd64", "arm64"] 37 | component_names = ["main"] 38 | 39 | [[RepoSuiteSettings]] 40 | repo_name = "master" 41 | suite_name = "unstable" 42 | signingkeys = ["DEADBEEF"] 43 | announce_emails = [] 44 | 45 | [[RepoSuiteSettings]] 46 | repo_name = "master" 47 | suite_name = "stable" 48 | signingkeys = ["DEADBEEF"] 49 | announce_emails = [] 50 | -------------------------------------------------------------------------------- /data/3rd-party.toml: -------------------------------------------------------------------------------- 1 | [Spears] 2 | britneyGitRepository = "https://salsa.debian.org/release-team/britney2.git" 3 | -------------------------------------------------------------------------------- /data/laniakea-lighthouse.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Laniakea Job Server 3 | Requires=postgresql.service 4 | After=syslog.target network.target 5 | ConditionPathExists=/etc/laniakea/base-config.toml 6 | 7 | [Service] 8 | Type=notify 9 | Restart=on-failure 10 | ProtectSystem=full 11 | User=_lklighthouse 12 | Group=nogroup 13 | ExecStart=@LIGHTHOUSE_INSTALL_BIN@ 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /data/laniakea-mailgun.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Laniakea Mailgun 3 | After=syslog.target network.target postgresql.service 4 | ConditionPathExists=/etc/laniakea/mailgun.toml 5 | 6 | [Service] 7 | Restart=on-failure 8 | RestartSec=15 9 | 10 | #ProtectSystem=full 11 | #ProtectHome=true 12 | 13 | User=lkmaster 14 | Group=nogroup 15 | ExecStart=@MAILGUN_INSTALL_BIN@ 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /data/laniakea-mirk.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Laniakea Matrix Bot 3 | After=syslog.target network.target 4 | ConditionPathExists=/etc/laniakea/mirk.toml 5 | 6 | [Service] 7 | Restart=on-failure 8 | RestartSec=15 9 | 10 | #ProtectSystem=full 11 | #ProtectHome=true 12 | 13 | User=lkweb 14 | Group=nogroup 15 | ExecStart=@MIRK_INSTALL_BIN@ 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /data/laniakea-scheduler.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Laniakea Maintenance Daemon 3 | Requires=postgresql.service 4 | After=syslog.target network.target 5 | ConditionPathExists=/etc/laniakea/base-config.toml 6 | 7 | [Service] 8 | Type=notify 9 | Restart=on-failure 10 | TimeoutStartSec=10 11 | 12 | User=lkmaster 13 | Group=lkmaster 14 | ExecStart=@SCHEDULER_INSTALL_BIN@ 15 | 16 | [Install] 17 | WantedBy=multi-user.target 18 | -------------------------------------------------------------------------------- /data/laniakea-webdash.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Laniakea Web Dashboard 3 | After=syslog.target network.target 4 | ConditionPathExists=/var/lib/laniakea/webdash/config.cfg 5 | 6 | [Service] 7 | Restart=on-failure 8 | 9 | #ProtectSystem=full 10 | #ProtectHome=true 11 | 12 | User=lkweb 13 | Group=www-data 14 | WorkingDirectory=@LKWEB_INSTALL_DIR@ 15 | 16 | RuntimeDirectory=laniakea-webdash 17 | ExecStart=/usr/bin/uwsgi --ini lkwebdash.ini 18 | 19 | [Install] 20 | WantedBy=multi-user.target 21 | -------------------------------------------------------------------------------- /data/laniakea-webswview.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Laniakea Web Software View 3 | After=syslog.target network.target 4 | ConditionPathExists=/var/lib/laniakea/webswview/config.cfg 5 | 6 | [Service] 7 | Restart=on-failure 8 | 9 | #ProtectSystem=full 10 | #ProtectHome=true 11 | 12 | User=lkweb 13 | Group=www-data 14 | WorkingDirectory=@LKSWWEB_INSTALL_DIR@ 15 | 16 | RuntimeDirectory=laniakea-webswview 17 | ExecStart=/usr/bin/uwsgi --ini lkwebswview.ini 18 | 19 | [Install] 20 | WantedBy=multi-user.target 21 | -------------------------------------------------------------------------------- /data/laniakea-webupload.service.in: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Laniakea artifact upload service 3 | After=syslog.target network.target 4 | ConditionPathExists=/var/lib/laniakea/webupload/config.cfg 5 | 6 | [Service] 7 | Restart=on-failure 8 | 9 | ProtectSystem=full 10 | ProtectHome=true 11 | 12 | User=lkweb 13 | Group=www-data 14 | WorkingDirectory=@LKUPLOAD_INSTALL_DIR@ 15 | 16 | RuntimeDirectory=laniakea-upload 17 | ExecStart=/usr/bin/uwsgi --ini lkwebupload.ini 18 | 19 | [Install] 20 | WantedBy=multi-user.target 21 | -------------------------------------------------------------------------------- /data/words/animals.txt: -------------------------------------------------------------------------------- 1 | alligator 2 | alpaca 3 | ant 4 | antelope 5 | ape 6 | armadillo 7 | baboon 8 | badger 9 | bat 10 | bear 11 | beaver 12 | bee 13 | beetle 14 | buffalo 15 | butterfly 16 | camel 17 | carabao 18 | caribou 19 | cat 20 | cattle 21 | cheetah 22 | chimpanzee 23 | chinchilla 24 | cicada 25 | clam 26 | cockroach 27 | cod 28 | coyote 29 | crab 30 | cricket 31 | crow 32 | deer 33 | dinosaur 34 | dog 35 | dolphin 36 | duck 37 | eel 38 | elephant 39 | elk 40 | ferret 41 | fish 42 | fly 43 | fox 44 | frog 45 | gerbil 46 | giraffe 47 | gnat 48 | gnu 49 | goat 50 | goldfish 51 | gorilla 52 | grasshopper 53 | guinea pig 54 | hamster 55 | hare 56 | hedgehog 57 | herring 58 | hippopotamus 59 | hornet 60 | horse 61 | hound 62 | hyena 63 | impala 64 | insect 65 | jackal 66 | jellyfish 67 | kangaroo 68 | leopard 69 | lion 70 | lizard 71 | llama 72 | locust 73 | louse 74 | mallard 75 | mammoth 76 | manatee 77 | marten 78 | mink 79 | minnow 80 | mole 81 | monkey 82 | moose 83 | mosquito 84 | mouse 85 | mule 86 | muskrat 87 | otter 88 | ox 89 | oyster 90 | panda 91 | pig 92 | platypus 93 | porcupine 94 | prairie dog 95 | pug 96 | rabbit 97 | raccoon 98 | reindeer 99 | rhinoceros 100 | salmon 101 | sardine 102 | scorpion 103 | seal 104 | serval 105 | shark 106 | sheep 107 | skunk 108 | snail 109 | snake 110 | spider 111 | squirrel 112 | termite 113 | tiger 114 | trout 115 | turtle 116 | walrus 117 | wasp 118 | weasel 119 | whale 120 | wolf 121 | wombat 122 | woodchuck 123 | worm 124 | yak 125 | yellow jacket 126 | zebra 127 | -------------------------------------------------------------------------------- /data/words/intermediate.txt: -------------------------------------------------------------------------------- 1 | bae 2 | bee 3 | big 4 | cat 5 | chill 6 | chin 7 | chuck 8 | chunk 9 | dad 10 | deep 11 | dig 12 | dill 13 | dinck 14 | dink 15 | dip 16 | dirt 17 | disc 18 | dock 19 | dog 20 | donk 21 | drake 22 | drill 23 | drink 24 | drunk 25 | duck 26 | dukes 27 | dumb 28 | dunk 29 | dust 30 | dutch 31 | flick 32 | hike 33 | jig 34 | kick 35 | kiss 36 | lick 37 | pink 38 | plump 39 | quick 40 | shrink 41 | sink 42 | small 43 | spike 44 | spout 45 | sprout 46 | stick 47 | stink 48 | suck 49 | swig 50 | thick 51 | tick 52 | tink 53 | truck 54 | twig 55 | wink 56 | yuck 57 | -------------------------------------------------------------------------------- /docs/.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | version: 2 5 | 6 | build: 7 | os: ubuntu-22.04 8 | tools: 9 | python: "3.12" 10 | apt_packages: 11 | - meson 12 | - gir1.2-appstream-1.0 13 | - python3-debian 14 | - python3-apt 15 | 16 | sphinx: 17 | configuration: docs/conf.py 18 | 19 | python: 20 | install: 21 | - requirements: docs/readthedocs-reqs.txt 22 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /docs/api/index.rst: -------------------------------------------------------------------------------- 1 | API 2 | === 3 | 4 | .. toctree:: 5 | :maxdepth: 4 6 | 7 | laniakea 8 | -------------------------------------------------------------------------------- /docs/api/laniakea.db.rst: -------------------------------------------------------------------------------- 1 | laniakea.db package 2 | =================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | laniakea.db.archive module 8 | -------------------------- 9 | 10 | .. automodule:: laniakea.db.archive 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | laniakea.db.base module 16 | ----------------------- 17 | 18 | .. automodule:: laniakea.db.base 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | laniakea.db.core module 24 | ----------------------- 25 | 26 | .. automodule:: laniakea.db.core 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | laniakea.db.debcheck module 32 | --------------------------- 33 | 34 | .. automodule:: laniakea.db.debcheck 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | laniakea.db.flatpak module 40 | -------------------------- 41 | 42 | .. automodule:: laniakea.db.flatpak 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | laniakea.db.isotope module 48 | -------------------------- 49 | 50 | .. automodule:: laniakea.db.isotope 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | laniakea.db.jobs module 56 | ----------------------- 57 | 58 | .. automodule:: laniakea.db.jobs 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | laniakea.db.spears module 64 | ------------------------- 65 | 66 | .. automodule:: laniakea.db.spears 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | laniakea.db.synchrotron module 72 | ------------------------------ 73 | 74 | .. automodule:: laniakea.db.synchrotron 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | laniakea.db.workers module 80 | -------------------------- 81 | 82 | .. automodule:: laniakea.db.workers 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | Module contents 88 | --------------- 89 | 90 | .. automodule:: laniakea.db 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | -------------------------------------------------------------------------------- /docs/api/laniakea.msgstream.rst: -------------------------------------------------------------------------------- 1 | laniakea.msgstream package 2 | ========================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | laniakea.msgstream.event\_msg module 8 | ------------------------------------ 9 | 10 | .. automodule:: laniakea.msgstream.event_msg 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | laniakea.msgstream.signedjson module 16 | ------------------------------------ 17 | 18 | .. automodule:: laniakea.msgstream.signedjson 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | laniakea.msgstream.signing module 24 | --------------------------------- 25 | 26 | .. automodule:: laniakea.msgstream.signing 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | Module contents 32 | --------------- 33 | 34 | .. automodule:: laniakea.msgstream 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | -------------------------------------------------------------------------------- /docs/api/laniakea.rst: -------------------------------------------------------------------------------- 1 | laniakea package 2 | ================ 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | laniakea.db 11 | laniakea.msgstream 12 | laniakea.utils 13 | 14 | Submodules 15 | ---------- 16 | 17 | laniakea.dakbridge module 18 | ------------------------- 19 | 20 | .. automodule:: laniakea.dakbridge 21 | :members: 22 | :undoc-members: 23 | :show-inheritance: 24 | 25 | laniakea.debcheck module 26 | ------------------------ 27 | 28 | .. automodule:: laniakea.debcheck 29 | :members: 30 | :undoc-members: 31 | :show-inheritance: 32 | 33 | laniakea.dud module 34 | ------------------- 35 | 36 | .. automodule:: laniakea.dud 37 | :members: 38 | :undoc-members: 39 | :show-inheritance: 40 | 41 | laniakea.flatpak\_util module 42 | ----------------------------- 43 | 44 | .. automodule:: laniakea.flatpak_util 45 | :members: 46 | :undoc-members: 47 | :show-inheritance: 48 | 49 | laniakea.git module 50 | ------------------- 51 | 52 | .. automodule:: laniakea.git 53 | :members: 54 | :undoc-members: 55 | :show-inheritance: 56 | 57 | laniakea.localconfig module 58 | --------------------------- 59 | 60 | .. automodule:: laniakea.localconfig 61 | :members: 62 | :undoc-members: 63 | :show-inheritance: 64 | 65 | laniakea.logging module 66 | ----------------------- 67 | 68 | .. automodule:: laniakea.logging 69 | :members: 70 | :undoc-members: 71 | :show-inheritance: 72 | 73 | laniakea.repository module 74 | -------------------------- 75 | 76 | .. automodule:: laniakea.repository 77 | :members: 78 | :undoc-members: 79 | :show-inheritance: 80 | 81 | Module contents 82 | --------------- 83 | 84 | .. automodule:: laniakea 85 | :members: 86 | :undoc-members: 87 | :show-inheritance: 88 | -------------------------------------------------------------------------------- /docs/api/laniakea.utils.rst: -------------------------------------------------------------------------------- 1 | laniakea.utils package 2 | ====================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | laniakea.utils.arches module 8 | ---------------------------- 9 | 10 | .. automodule:: laniakea.utils.arches 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | laniakea.utils.base64 module 16 | ---------------------------- 17 | 18 | .. automodule:: laniakea.utils.base64 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | laniakea.utils.command module 24 | ----------------------------- 25 | 26 | .. automodule:: laniakea.utils.command 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | laniakea.utils.deb822 module 32 | ---------------------------- 33 | 34 | .. automodule:: laniakea.utils.deb822 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | laniakea.utils.gpg module 40 | ------------------------- 41 | 42 | .. automodule:: laniakea.utils.gpg 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | laniakea.utils.json module 48 | -------------------------- 49 | 50 | .. automodule:: laniakea.utils.json 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | laniakea.utils.misc module 56 | -------------------------- 57 | 58 | .. automodule:: laniakea.utils.misc 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | Module contents 64 | --------------- 65 | 66 | .. automodule:: laniakea.utils 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | 3 | import os 4 | import sys 5 | 6 | # -- Project information ----------------------------------------------------- 7 | 8 | project = 'Laniakea' 9 | copyright = '2016-2024, Matthias Klumpp' 10 | author = 'Matthias Klumpp' 11 | 12 | # The full version, including alpha/beta/rc tags 13 | release = '0.1' 14 | 15 | # -- General configuration --------------------------------------------------- 16 | thisfile = __file__ 17 | if not os.path.isabs(thisfile): 18 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 19 | sys.path.insert(0, os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', 'src'))) 20 | on_rtd = os.environ.get('READTHEDOCS') == 'True' 21 | 22 | html_theme = 'piccolo_theme' 23 | html_theme_options = {"show_prev_next": True} 24 | 25 | extensions = [ 26 | 'sphinx.ext.autodoc', 27 | 'sphinx.ext.coverage', 28 | 'sphinx.ext.intersphinx', 29 | 'sphinx_autodoc_typehints', 30 | ] 31 | 32 | if on_rtd: 33 | autodoc_mock_imports = ['gi', 'systemd', 'apt_pkg'] 34 | 35 | # Intersphinx 36 | intersphinx_mapping = {'python': ('https://docs.python.org/3', None)} 37 | 38 | # Add any paths that contain templates here, relative to this directory. 39 | templates_path = ['_templates'] 40 | 41 | # List of patterns, relative to source directory, that match files and 42 | # directories to ignore when looking for source files. 43 | # This pattern also affects html_static_path and html_extra_path. 44 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 45 | 46 | 47 | # -- Options for HTML output ------------------------------------------------- 48 | 49 | # Add any paths that contain custom static files (such as style sheets) here, 50 | # relative to this directory. They are copied after the builtin static files, 51 | # so a file named "default.css" will overwrite the builtin "default.css". 52 | html_static_path = ['_static'] 53 | -------------------------------------------------------------------------------- /docs/general/datasync.rst: -------------------------------------------------------------------------------- 1 | DataSync - synchronize data from 3rd-party internal sources 2 | =========================================================== 3 | 4 | The DataSync utility is a workaround to import archive data from a 5 | repository that is not under Laniakea’s direct control. This module mght 6 | be superseded by a more sophisticated solution in future. 7 | 8 | TODO 9 | ---- 10 | -------------------------------------------------------------------------------- /docs/general/index.rst: -------------------------------------------------------------------------------- 1 | General 2 | ======= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :caption: Contents: 7 | 8 | initial-setup.rst 9 | worker-setup.rst 10 | datasync.rst 11 | lighthouse.rst 12 | rubicon.rst 13 | tools/index.rst 14 | -------------------------------------------------------------------------------- /docs/general/lighthouse.rst: -------------------------------------------------------------------------------- 1 | Lighthouse - communication relay 2 | ================================ 3 | 4 | Laniakea modules are almost always their own executables or even 5 | services. This allows to run them on separate machines, to improve 6 | security by isolation or to balance load. 7 | 8 | The *Lighthouse* core module is a daemon that provides a way for 9 | Laniakea modules to get notified about changes, distribute jobs to them 10 | and receive information to store in the database. 11 | 12 | There can be an arbitrary number of Lighthouse instances on multiple 13 | servers. Due to Lighthouse directly distributing jobs and interacting 14 | with the central database, currently each Lighthouse server needs write 15 | access to a Postgres database. 16 | 17 | TODO 18 | ---- 19 | 20 | About the name 21 | ^^^^^^^^^^^^^^ 22 | 23 | A lighthouse guides ships on the sea to stay on course. The same way the 24 | Lighthouse module is a fixpoint for Laniakea modules, and is the place 25 | they gets tasks and information from (if they don’t have a direct 26 | database connection already). 27 | -------------------------------------------------------------------------------- /docs/general/rubicon.rst: -------------------------------------------------------------------------------- 1 | Rubicon - import artifacts into a trusted area 2 | ============================================== 3 | 4 | Rubicon imports (build)artifacts from a less-trusted space into a 5 | trusted area. It verifies GPG signatures of the artifacts against a 6 | trusted keyring, and if the files can be trusted, moves them to a 7 | predefined location. 8 | 9 | It can be used for importing arbitrary files, as long as they are 10 | accompanied by a signed ``.dud`` (“Debian Upload Description”) file. 11 | 12 | TODO 13 | ---- 14 | 15 | 16 | About the name 17 | ^^^^^^^^^^^^^^ 18 | 19 | The `Rubicon `__ river was 20 | historically the border between the Roman province Cisalpine Gaul and 21 | Italy. Governors of northern provinces were not allowed to cross it with 22 | their troups, doing so was a capital offense (something that a certain 23 | Julius Caesar famously ignored). The ``rubicon`` tool ensures only 24 | trusted allies cross the border in Laniakea. 25 | -------------------------------------------------------------------------------- /docs/general/tools/index.rst: -------------------------------------------------------------------------------- 1 | CLI Tools 2 | ========= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :caption: Contents: 7 | 8 | lk-admin.rst 9 | lk-keytool.rst 10 | -------------------------------------------------------------------------------- /docs/general/tools/lk-admin.rst: -------------------------------------------------------------------------------- 1 | The lk-admin tool 2 | ================= 3 | 4 | Administer your Laniakea instance from the command line. 5 | 6 | TODO 7 | ---- 8 | -------------------------------------------------------------------------------- /docs/general/tools/lk-keytool.rst: -------------------------------------------------------------------------------- 1 | The lk-keytool tool 2 | =================== 3 | 4 | Generate and deploy cryptographic keys for Laniakea services using GnuPG 5 | or CurveZMQ. 6 | 7 | TODO 8 | ---- 9 | -------------------------------------------------------------------------------- /docs/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea Documentation 2 | 3 | r = run_command(pymod_check_exe, [pymod_check_arg, 'docs'], check: false) 4 | if r.returncode() != 0 5 | error(r.stderr().strip()) 6 | endif 7 | 8 | sphinxb_exe = find_program('sphinx-build') 9 | sphinx_apidoc_exe = find_program('sphinx-apidoc') 10 | 11 | # maintainer target to generate documentation 12 | run_target ('docs-html', 13 | command: [sphinxb_exe, 14 | meson.current_source_dir(), 15 | join_paths(build_root, 'docs-html'), 16 | '-b', 'html' 17 | ] 18 | ) 19 | 20 | # maintainer target to update API doc templates 21 | run_target ('update-apidoc', 22 | command: [sphinx_apidoc_exe, 23 | '-o', join_paths(meson.current_source_dir(), 'api'), 24 | join_paths(source_root, 'src'), 25 | '--tocfile', 'index', 26 | '-H', 'API' 27 | ] 28 | ) 29 | -------------------------------------------------------------------------------- /docs/modules/debcheck.rst: -------------------------------------------------------------------------------- 1 | DebCheck - find issues in package installability 2 | ================================================ 3 | 4 | The DebCheck optional modules uses ``dose3`` to determine which packages 5 | are installable and have their build dependencies satisfied. Its reports 6 | can be viewed with the web UI. DebCheck is a requirement of other 7 | modules, e.g. Ariadne. 8 | 9 | TODO 10 | ---- 11 | -------------------------------------------------------------------------------- /docs/modules/index.rst: -------------------------------------------------------------------------------- 1 | Modules 2 | ======= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :caption: Contents: 7 | 8 | debcheck.rst 9 | isotope.rst 10 | planter.rst 11 | spears.rst 12 | synchrotron.rst 13 | -------------------------------------------------------------------------------- /docs/modules/isotope.rst: -------------------------------------------------------------------------------- 1 | Isotope - build disk images 2 | =========================== 3 | 4 | TODO 5 | ---- 6 | -------------------------------------------------------------------------------- /docs/modules/planter.rst: -------------------------------------------------------------------------------- 1 | Planter - generate metapackage seeds 2 | ==================================== 3 | 4 | The Planter module is a thin wrapper around ``germinator`` to generate a 5 | table of which packages are pulled in for a metapackage, and why. It is 6 | commonly used to build metapackages to select the default components 7 | found on the OS. 8 | 9 | TODO 10 | ---- 11 | -------------------------------------------------------------------------------- /docs/modules/spears.rst: -------------------------------------------------------------------------------- 1 | Spears - migrate packages between suites 2 | ======================================== 3 | 4 | Spears is a wrapper around ``Britney2``, which is used to migrate 5 | packages from a source to a target suite as long as they do not break 6 | installability in the target suite and fulfill other criteria, e.g. pass 7 | tests or fulfill a time limit. 8 | 9 | TODO 10 | ---- 11 | 12 | 13 | About the name 14 | ^^^^^^^^^^^^^^ 15 | 16 | The module is named after singer Britney Spears, for obvious reasons 17 | (the first result you get when you search for “Britney” on the 18 | internet). 19 | -------------------------------------------------------------------------------- /docs/modules/synchrotron.rst: -------------------------------------------------------------------------------- 1 | Synchrotron - synchronize packages with another distribution 2 | ============================================================ 3 | 4 | Synchrotron can import packages from another distribution into the 5 | repositories of the target, ensuring changes made in the target 6 | distribution are kept. It provides various methods to control the flow 7 | of packages. At the moment, synchronization is a one-way street from the 8 | source distribution to the target derivative. 9 | 10 | TODO 11 | ---- 12 | 13 | 14 | About the name 15 | ^^^^^^^^^^^^^^ 16 | -------------------------------------------------------------------------------- /docs/readthedocs-reqs.txt: -------------------------------------------------------------------------------- 1 | APScheduler 2 | Pebble 3 | PyNaCl 4 | PyYAML 5 | SQLAlchemy 6 | alembic 7 | click 8 | firehose 9 | humanize 10 | marshmallow 11 | psycopg2 12 | python-debian 13 | pyzmq 14 | requests 15 | rich 16 | setproctitle 17 | tomlkit 18 | tornado 19 | voluptuous 20 | Flask 21 | Flask-Caching 22 | Flask-Login 23 | flask-rebar 24 | mautrix 25 | Pygments 26 | Sphinx 27 | piccolo-theme 28 | sphinx-autodoc-typehints 29 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | -r ../requirements.txt 2 | Pygments>=2.6 3 | Sphinx>=6.0 4 | piccolo-theme>=0.14 5 | sphinx-autodoc-typehints~=1.12.0 6 | -------------------------------------------------------------------------------- /docs/web/index.rst: -------------------------------------------------------------------------------- 1 | Web Services 2 | ============ 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :caption: Contents: 7 | -------------------------------------------------------------------------------- /meson.build: -------------------------------------------------------------------------------- 1 | project('Laniakea', 'c', 2 | meson_version: '>=1.0', 3 | license: 'LGPL-3.0+', 4 | version: '0.1' 5 | ) 6 | 7 | source_root = meson.project_source_root() 8 | build_root = meson.project_build_root() 9 | 10 | pymod = import('python') 11 | py = pymod.find_installation('python3') 12 | 13 | # 14 | # Dependencies 15 | # 16 | python_min_version = '3.11' 17 | systemd_dep = dependency('systemd') 18 | 19 | if not py.language_version().version_compare('>=' + python_min_version) 20 | error('Python version is too low. We require at least ' + python_min_version + ' to run.') 21 | endif 22 | 23 | # Python dependencies 24 | pymod_check_exe = find_program(join_paths(source_root, 'pyreqcheck.py')) 25 | pymod_check_arg = ['--check-group'] 26 | r = run_command(pymod_check_exe, [pymod_check_arg, 'base'], check: false) 27 | if r.returncode() != 0 28 | error(r.stderr().strip()) 29 | endif 30 | 31 | # maintainer target to update requirements files 32 | run_target ('update-requirements', 33 | command: [pymod_check_exe, ['--write-requirements']] 34 | ) 35 | 36 | if build_machine.system() != 'linux' 37 | error('Laniakea needs Linux and GLibc to work properly, as it relies on system calls like renameat2 to function properly.') 38 | endif 39 | 40 | # 41 | # Lanikaea Modules 42 | # 43 | subdir('src') 44 | 45 | # 46 | # Data 47 | # 48 | subdir('data') 49 | 50 | # 51 | # Tests 52 | # 53 | subdir('tests') 54 | 55 | # 56 | # Documentation 57 | # 58 | if get_option('docs') 59 | subdir('docs') 60 | endif 61 | -------------------------------------------------------------------------------- /requirements.base.txt: -------------------------------------------------------------------------------- 1 | APScheduler~=3.9.1 2 | Pebble>=4.6 3 | PyGObject 4 | PyNaCl~=1.5.0 5 | PyYAML>=5.3.1 6 | SQLAlchemy<2.0,>=1.4 7 | alembic~=1.8.1.dev0 8 | click>=7.1 9 | firehose~=0.5 10 | humanize 11 | marshmallow>=3.18 12 | psycopg2>=2.7.7 13 | python-apt 14 | python-debian~=0.1.49 15 | pyzmq~=24.0.1 16 | requests~=2.28.1 17 | rich>=12.4 18 | setproctitle~=1.3.1 19 | systemd-python 20 | tomlkit>=0.8 21 | tornado~=6.2 22 | voluptuous~=0.12.2 23 | -------------------------------------------------------------------------------- /requirements.matrix.txt: -------------------------------------------------------------------------------- 1 | mautrix>=0.8.18 2 | -------------------------------------------------------------------------------- /requirements.tests.txt: -------------------------------------------------------------------------------- 1 | black 2 | flake8 3 | isort 4 | mypy 5 | pylint 6 | pylint-flask 7 | pylint-sqlalchemy 8 | pytest 9 | pytest-flask 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | -r requirements.base.txt 2 | -r requirements.web.txt 3 | -r requirements.matrix.txt 4 | -------------------------------------------------------------------------------- /requirements.web.txt: -------------------------------------------------------------------------------- 1 | Flask~=2.2.2 2 | Flask-Caching>=2.0 3 | Flask-Login~=0.6.2 4 | flask-rebar~=2.3.0 5 | -------------------------------------------------------------------------------- /src/debcheck/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/src/debcheck/__init__.py -------------------------------------------------------------------------------- /src/debcheck/debcheck: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 10 | 11 | if __name__ == '__main__': 12 | from debcheck import cli 13 | sys.exit(cli.run(thisfile, sys.argv[1:])) 14 | -------------------------------------------------------------------------------- /src/debcheck/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - DebCheck 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/debcheck/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build'], 6 | ) 7 | -------------------------------------------------------------------------------- /src/keytool/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - KeyTool 2 | 3 | install_data('keytool.py', install_dir: 'bin', rename: 'lk-keytool') 4 | -------------------------------------------------------------------------------- /src/laniakea/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | import sys 9 | 10 | __version__ = '0.1.0' 11 | 12 | thisfile = __file__ 13 | if not os.path.isabs(thisfile): 14 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 15 | lk_py_directory = os.path.normpath(os.path.join(os.path.dirname(thisfile))) 16 | sys.path.append(lk_py_directory) 17 | 18 | from laniakea.db import LkModule 19 | from laniakea.localconfig import LocalConfig, get_config_file 20 | 21 | __all__ = ['LocalConfig', 'get_config_file', 'LkModule'] 22 | -------------------------------------------------------------------------------- /src/laniakea/alembic.ini: -------------------------------------------------------------------------------- 1 | # A generic, single database configuration. 2 | 3 | [alembic] 4 | # path to migration scripts 5 | script_location = alembic 6 | 7 | # template used to generate migration files 8 | # file_template = %%(rev)s_%%(slug)s 9 | 10 | # timezone to use when rendering the date 11 | # within the migration file as well as the filename. 12 | # string value is passed to dateutil.tz.gettz() 13 | # leave blank for localtime 14 | # timezone = 15 | 16 | # max length of characters to apply to the 17 | # "slug" field 18 | # truncate_slug_length = 40 19 | 20 | # set to 'true' to run the environment during 21 | # the 'revision' command, regardless of autogenerate 22 | # revision_environment = false 23 | 24 | # set to 'true' to allow .pyc and .pyo files without 25 | # a source .py file to be detected as revisions in the 26 | # versions/ directory 27 | # sourceless = false 28 | 29 | # version location specification; this defaults 30 | # to alembic/versions. When using multiple version 31 | # directories, initial revisions must be specified with --version-path 32 | # version_locations = %(here)s/bar %(here)s/bat alembic/versions 33 | 34 | # the output encoding used when revision files 35 | # are written from script.py.mako 36 | # output_encoding = utf-8 37 | 38 | sqlalchemy.url = postgresql://laniakea 39 | 40 | [exclude_tables] 41 | tables = maintenance_jobs 42 | 43 | # Logging configuration 44 | [loggers] 45 | keys = root,sqlalchemy,alembic 46 | 47 | [handlers] 48 | keys = console 49 | 50 | [formatters] 51 | keys = generic 52 | 53 | [logger_root] 54 | level = WARN 55 | handlers = console 56 | qualname = 57 | 58 | [logger_sqlalchemy] 59 | level = WARN 60 | handlers = 61 | qualname = sqlalchemy.engine 62 | 63 | [logger_alembic] 64 | level = INFO 65 | handlers = 66 | qualname = alembic 67 | 68 | [handler_console] 69 | class = StreamHandler 70 | args = (sys.stderr,) 71 | level = NOTSET 72 | formatter = generic 73 | 74 | [formatter_generic] 75 | format = %(levelname)-5.5s [%(name)s] %(message)s 76 | datefmt = %H:%M:%S 77 | -------------------------------------------------------------------------------- /src/laniakea/alembic/script.py.mako: -------------------------------------------------------------------------------- 1 | """${message} 2 | 3 | Revision ID: ${up_revision} 4 | Revises: ${down_revision | comma,n} 5 | Create Date: ${create_date} 6 | 7 | """ 8 | # flake8: noqa 9 | 10 | from alembic import op 11 | import sqlalchemy as sa 12 | ${imports if imports else ""} 13 | 14 | # revision identifiers, used by Alembic. 15 | revision = ${repr(up_revision)} 16 | down_revision = ${repr(down_revision)} 17 | branch_labels = ${repr(branch_labels)} 18 | depends_on = ${repr(depends_on)} 19 | 20 | 21 | def upgrade(): 22 | ${upgrades if upgrades else "pass"} 23 | 24 | 25 | def downgrade(): 26 | ${downgrades if downgrades else "pass"} 27 | -------------------------------------------------------------------------------- /src/laniakea/alembic/versions/34ccc7e6f9b8_baseline.py: -------------------------------------------------------------------------------- 1 | """root 2 | 3 | Revision ID: 34ccc7e6f9b8 4 | Revises: - 5 | Create Date: 2020-08-24 17:20:58.146028 6 | 7 | """ 8 | 9 | # flake8: noqa 10 | # pylint: disable=W,R,C 11 | 12 | import sqlalchemy as sa 13 | from alembic import op 14 | 15 | # revision identifiers, used by Alembic. 16 | revision = '34ccc7e6f9b8' 17 | down_revision = None 18 | branch_labels = None 19 | depends_on = None 20 | 21 | 22 | def upgrade(): 23 | pass 24 | 25 | 26 | def downgrade(): 27 | pass 28 | -------------------------------------------------------------------------------- /src/laniakea/archive/__init__.py: -------------------------------------------------------------------------------- 1 | from laniakea.archive.utils import ( 2 | split_epoch, 3 | repo_suite_settings_for, 4 | binaries_exist_for_package, 5 | find_latest_source_package, 6 | repo_suite_settings_for_debug, 7 | ) 8 | from laniakea.archive.manage import copy_source_package, remove_source_package 9 | from laniakea.archive.pkgimport import ( 10 | UploadHandler, 11 | PackageImporter, 12 | ArchiveImportError, 13 | ArchivePackageExistsError, 14 | ) 15 | from laniakea.archive.uploadermgr import import_key_file_for_uploader 16 | 17 | __all__ = [ 18 | 'import_key_file_for_uploader', 19 | 'PackageImporter', 20 | 'UploadHandler', 21 | 'ArchiveImportError', 22 | 'ArchivePackageExistsError', 23 | 'copy_source_package', 24 | 'remove_source_package', 25 | 'repo_suite_settings_for', 26 | 'repo_suite_settings_for_debug', 27 | 'split_epoch', 28 | 'find_latest_source_package', 29 | 'binaries_exist_for_package', 30 | ] 31 | -------------------------------------------------------------------------------- /src/laniakea/ariadne/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2022-2023 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from laniakea.ariadne.maintenance import ( 8 | retry_stalled_jobs, 9 | delete_orphaned_jobs, 10 | remove_superfluous_pending_jobs, 11 | ) 12 | from laniakea.ariadne.package_jobs import schedule_package_builds_for_source 13 | 14 | __all__ = [ 15 | 'schedule_package_builds_for_source', 16 | 'remove_superfluous_pending_jobs', 17 | 'delete_orphaned_jobs', 18 | 'retry_stalled_jobs', 19 | ] 20 | -------------------------------------------------------------------------------- /src/laniakea/db/__init__.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa 2 | 3 | from .base import Database, print_query, session_scope, session_factory 4 | from .core import ( 5 | LkModule, 6 | config_get_value, 7 | config_set_value, 8 | config_get_distro_tag, 9 | config_set_distro_tag, 10 | config_get_project_name, 11 | config_set_project_name, 12 | ) 13 | from .jobs import * 14 | from .stats import * 15 | from .spears import * 16 | from .archive import * 17 | from .flatpak import * 18 | from .isotope import * 19 | from .workers import * 20 | from .debcheck import * 21 | from .synchrotron import * 22 | -------------------------------------------------------------------------------- /src/laniakea/db/isotope.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import enum 8 | from uuid import uuid4 9 | 10 | from sqlalchemy import Enum, Text, Column, String, Boolean, Integer 11 | from sqlalchemy.dialects.postgresql import ARRAY 12 | 13 | from .base import UUID, Base 14 | 15 | 16 | class ImageFormat(enum.IntEnum): 17 | ''' 18 | Kind of the image to build. 19 | ''' 20 | 21 | UNKNOWN = 0 22 | ISO = enum.auto() 23 | IMG = enum.auto() 24 | 25 | def __str__(self): 26 | if self.value == self.ISO: 27 | return 'iso' 28 | if self.value == self.IMG: 29 | return 'img' 30 | return 'ImageFormat.' + str(self.name) 31 | 32 | 33 | class ImageBuildRecipe(Base): 34 | ''' 35 | Instructions on how to do an automatic ISO image build. 36 | ''' 37 | 38 | __tablename__ = 'image_build_recipes' 39 | 40 | uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid4) 41 | name = Column(Text(), nullable=False, unique=True) # A unique name identifying this recipe 42 | 43 | format = Column(Enum(ImageFormat)) # The image format to build (e.g. ISO or IMG) 44 | distribution = Column(Text(), nullable=False) # Name of the distribution, e.g. "Tanglu" 45 | suite = Column(Text(), nullable=False) # Suite of the distribution to build an image for 46 | environment = Column(Text(), nullable=False) # The environment (GNOME, Plasma, server, ...) to use 47 | style = Column(Text(), nullable=True) # Style of the image (e.g. "oem" or "live") 48 | architectures = Column(ARRAY(String(80))) # Architectures to build the image for 49 | # Architecture of the host that is allowed to build the images, or "any" 50 | host_architecture = Column(String(80), nullable=False) 51 | 52 | git_url = Column(Text(), nullable=False) # Git repository URL with the live-build scripts / other build recipes 53 | result_move_to = Column(Text()) # Local or remote URL to copy the resulting build artifacts to 54 | # Number of images to retain, oldest images will be deleted first. -1 to keep images forever 55 | retain_images_n = Column(Integer(), default=-1) 56 | create_latest_symlink = Column(Boolean(), default=False) # Create a "latest" symlink directory to the latest build 57 | -------------------------------------------------------------------------------- /src/laniakea/db/workers.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import enum 8 | from enum import IntEnum 9 | from uuid import uuid4 10 | from datetime import datetime 11 | 12 | from sqlalchemy import Enum, Text, Column, Boolean, DateTime 13 | from sqlalchemy.dialects.postgresql import JSON, ARRAY 14 | 15 | from .base import UUID, Base 16 | 17 | 18 | class WorkerStatus(IntEnum): 19 | ''' 20 | State this worker is in. 21 | ''' 22 | 23 | UNKNOWN = 0 24 | ACTIVE = enum.auto() 25 | IDLE = enum.auto() 26 | MISSING = enum.auto() 27 | DEAD = enum.auto() 28 | 29 | 30 | class SparkWorker(Base): 31 | ''' 32 | An external machine/service that takes tasks from a Lighthouse server. 33 | ''' 34 | 35 | __tablename__ = 'spark_workers' 36 | 37 | uuid = Column(UUID(as_uuid=True), primary_key=True, default=uuid4) 38 | 39 | name = Column(Text()) # The machine/worker name 40 | owner = Column(Text(), nullable=True) # Owner of this worker 41 | 42 | time_created = Column(DateTime(), default=datetime.utcnow) # Time when this worker was registered/created 43 | 44 | accepts = Column(ARRAY(Text())) # Modules this worker will accept jobs for 45 | architectures = Column(ARRAY(Text())) # Architectures this worker will accept jobs for 46 | 47 | status = Column(Enum(WorkerStatus)) # Status/health of this machine 48 | enabled = Column(Boolean()) # Whether this worker should receive jobs or not 49 | 50 | last_ping = Column(DateTime()) # Time when we last got a message from the worker 51 | 52 | data = Column(JSON) # Custom worker properties 53 | -------------------------------------------------------------------------------- /src/laniakea/flatpak_util.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2019-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import shutil 8 | 9 | from laniakea import LocalConfig 10 | from laniakea.db import FlatpakRepository 11 | from laniakea.utils import safe_run_forwarded 12 | 13 | 14 | class FlatpakUtil: 15 | ''' 16 | Interface with the Flatpak CLI tools to perform verious administrative 17 | actions on repositories. 18 | ''' 19 | 20 | def __init__(self): 21 | self._flatpak_exe = shutil.which('flatpak') 22 | self._ostree_exe = shutil.which('ostree') 23 | self._lconf = LocalConfig() 24 | 25 | if not self._flatpak_exe: 26 | raise Exception('Unable to find the "flatpak" binary, can not modify Flatpak repositories.') 27 | if not self._ostree_exe: 28 | raise Exception('Unable to find the "ostree" binary, can not modify Flatpak repositories.') 29 | 30 | def _run_ostree(self, args): 31 | '''Run an OSTree CLI command''' 32 | cmd = [self._ostree_exe] 33 | cmd.extend(args) 34 | return safe_run_forwarded(cmd) 35 | 36 | def _run_flatpak(self, args): 37 | '''Run a Flatpak CLI command''' 38 | cmd = [self._flatpak_exe] 39 | cmd.extend(args) 40 | return safe_run_forwarded(cmd) 41 | 42 | def init_repo(self, repo: FlatpakRepository, repo_path: str): 43 | '''Initialize a new, empty Flatpak repository''' 44 | 45 | ost_args = ['init', '--mode', 'archive-z2', '--repo', repo_path] 46 | self._run_ostree(ost_args) 47 | 48 | fp_args = [ 49 | 'build-update-repo', 50 | '--title', 51 | repo.title, 52 | '--default-branch', 53 | repo.default_branch, 54 | '--collection-id', 55 | repo.collection_id, 56 | '--gpg-sign', 57 | repo.gpg_key_id, 58 | '--gpg-homedir', 59 | self._lconf.secret_gpg_home_dir, 60 | ] 61 | if repo.comment: 62 | fp_args.extend(['--comment', repo.comment]) 63 | if repo.description: 64 | fp_args.extend(['--description', repo.description]) 65 | if repo.url_homepage: 66 | fp_args.extend(['--homepage', repo.url_homepage]) 67 | if repo.url_icon: 68 | fp_args.extend(['--icon', repo.url_icon]) 69 | 70 | fp_args.append(repo_path) 71 | self._run_flatpak(fp_args) 72 | -------------------------------------------------------------------------------- /src/laniakea/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Shared Python Module 2 | 3 | install_subdir( 4 | '.', 5 | install_dir: py.get_install_dir() / 'laniakea', 6 | exclude_directories: ['__pycache__'], 7 | exclude_files: ['meson.build'], 8 | strip_directory: true 9 | ) 10 | install_symlink( 11 | 'laniakea', 12 | install_dir: 'lib/laniakea', 13 | pointing_to: py.get_install_dir() / 'laniakea', 14 | ) 15 | 16 | apt_ftparchive_exe = find_program('apt-ftparchive', required: false) 17 | if not apt_ftparchive_exe.found() 18 | error('Unable to find `apt-ftparchive`. Please install `apt-utils` to continue.') 19 | endif 20 | 21 | bwrap_exe = find_program('bwrap', required: false) 22 | if not bwrap_exe.found() 23 | error('Unable to find `bwrap`. Please install `bubblewrap` to continue.') 24 | endif 25 | -------------------------------------------------------------------------------- /src/laniakea/msgstream/__init__.py: -------------------------------------------------------------------------------- 1 | from laniakea.msgstream.signing import keyfile_read_verify_key, keyfile_read_signing_key 2 | from laniakea.msgstream.event_msg import ( 3 | EventEmitter, 4 | create_message_tag, 5 | create_event_message, 6 | create_submit_socket, 7 | submit_event_message, 8 | verify_event_message, 9 | create_event_listen_socket, 10 | event_message_is_valid_and_signed, 11 | ) 12 | from laniakea.msgstream.signedjson import SignatureVerifyException 13 | 14 | __all__ = [ 15 | 'create_message_tag', 16 | 'create_event_message', 17 | 'verify_event_message', 18 | 'event_message_is_valid_and_signed', 19 | 'SignatureVerifyException', 20 | 'keyfile_read_verify_key', 21 | 'keyfile_read_signing_key', 22 | 'create_submit_socket', 23 | 'submit_event_message', 24 | 'create_event_listen_socket', 25 | 'EventEmitter', 26 | ] 27 | -------------------------------------------------------------------------------- /src/laniakea/typing.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | # flake8: noqa 8 | # pylint: disable=wildcard-import,unused-wildcard-import 9 | 10 | import os 11 | from typing import * 12 | 13 | # type for file paths 14 | PathUnion = Union[str, os.PathLike] 15 | -------------------------------------------------------------------------------- /src/laniakea/utils/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from laniakea.utils.json import json_compact_dump 8 | from laniakea.utils.misc import ( 9 | LockError, 10 | cd, 11 | listify, 12 | stringify, 13 | safe_strip, 14 | split_strip, 15 | download_file, 16 | is_remote_url, 17 | random_string, 18 | process_file_lock, 19 | set_process_title, 20 | datetime_to_rfc2822_string, 21 | get_dir_shorthand_for_uuid, 22 | ) 23 | from laniakea.utils.arches import arch_matches, any_arch_matches 24 | from laniakea.utils.base64 import decode_base64, encode_base64 25 | from laniakea.utils.deb822 import Changes 26 | from laniakea.utils.command import ( 27 | safe_run, 28 | run_command, 29 | run_forwarded, 30 | safe_run_forwarded, 31 | ) 32 | from laniakea.utils.fileutil import ( 33 | safe_rename, 34 | open_compressed, 35 | hardlink_or_copy, 36 | check_filename_safe, 37 | ) 38 | from laniakea.utils.traceback import ( 39 | decrypt_traceback_string, 40 | format_encrypted_traceback, 41 | ) 42 | 43 | __all__ = [ 44 | 'arch_matches', 45 | 'any_arch_matches', 46 | 'Changes', 47 | 'datetime_to_rfc2822_string', 48 | 'get_dir_shorthand_for_uuid', 49 | 'random_string', 50 | 'run_command', 51 | 'safe_run', 52 | 'run_forwarded', 53 | 'safe_run_forwarded', 54 | 'LockError', 55 | 'cd', 56 | 'listify', 57 | 'stringify', 58 | 'is_remote_url', 59 | 'download_file', 60 | 'split_strip', 61 | 'safe_strip', 62 | 'open_compressed', 63 | 'encode_base64', 64 | 'decode_base64', 65 | 'json_compact_dump', 66 | 'check_filename_safe', 67 | 'process_file_lock', 68 | 'safe_rename', 69 | 'hardlink_or_copy', 70 | 'set_process_title', 71 | 'format_encrypted_traceback', 72 | 'decrypt_traceback_string', 73 | ] 74 | -------------------------------------------------------------------------------- /src/laniakea/utils/arches.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from laniakea.utils.command import run_command 8 | 9 | 10 | def arch_matches(arch, alias): 11 | ''' 12 | Check if given arch `arch` matches the other arch `alias`. This is most 13 | useful for the complex any-* rules. 14 | ''' 15 | 16 | if arch == alias: 17 | return True 18 | 19 | if arch == 'all' or arch == 'source': 20 | # These pseudo-arches does not match any wildcards or aliases 21 | return False 22 | 23 | if alias == 'any': 24 | # The 'any' wildcard matches all *real* architectures 25 | return True 26 | 27 | if alias == 'linux-any': 28 | # GNU/Linux arches are named 29 | # Other Linux arches are named -linux- 30 | return '-' not in arch or 'linux' in arch.split('-') 31 | 32 | if alias.endswith('-any'): 33 | # Non-Linux GNU/ arches are named - 34 | # Other non-Linux arches are named -- 35 | osname, _ = alias.split('-', 1) 36 | return osname in arch.split('-') 37 | 38 | if '-' not in arch and '-' not in alias: 39 | return False 40 | 41 | # This is a performance disaster 42 | # Hopefully we'll rarely get here 43 | out, err, ret = run_command(["/usr/bin/dpkg-architecture", "-a%s" % (arch), "-i%s" % (alias)]) 44 | return ret == 0 45 | 46 | 47 | def any_arch_matches(architectures, aliases): 48 | ''' 49 | Check if any architecture in iterable `architectures` matches any architecture wildcard 50 | in `aliases`. 51 | ''' 52 | 53 | if type(architectures) is str: 54 | architectures = [architectures] 55 | if type(aliases) is str: 56 | aliases = [aliases] 57 | 58 | for arch in architectures: 59 | for alias in aliases: 60 | if arch_matches(arch, alias): 61 | return True 62 | return False 63 | -------------------------------------------------------------------------------- /src/laniakea/utils/base64.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2019-2022 Matthias Klumpp 4 | # Copyright (C) 2014-2015 OpenMarket Ltd 5 | # 6 | # SPDX-License-Identifier: LGPL-3.0+ AND Apache-2.0 7 | 8 | import base64 9 | 10 | 11 | def encode_base64(input_bytes, urlsafe=False): 12 | ''' 13 | Encode bytes as a base64 string without any padding. 14 | ''' 15 | 16 | encode = base64.urlsafe_b64encode if urlsafe else base64.b64encode 17 | output_bytes = encode(input_bytes) 18 | output_string = output_bytes.decode('ascii') 19 | return output_string.rstrip('=') 20 | 21 | 22 | def decode_base64(input_string): 23 | ''' 24 | Decode a base64 string to bytes inferring padding from the length of the 25 | string. 26 | ''' 27 | 28 | input_bytes = input_string.encode('ascii') 29 | input_len = len(input_bytes) 30 | padding = b'=' * (3 - ((input_len + 3) % 4)) 31 | decode = base64.b64decode 32 | if '-' in input_string or '_' in input_string: 33 | decode = base64.urlsafe_b64decode 34 | output_bytes = decode(input_bytes + padding) 35 | return output_bytes 36 | -------------------------------------------------------------------------------- /src/laniakea/utils/json.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import json 8 | 9 | 10 | def json_compact_dump(obj, as_bytes=False): 11 | ''' 12 | Convert :obj to JSON string reproducibly and 13 | in the most compact form possible. 14 | ''' 15 | s = json.dumps(obj, ensure_ascii=False, separators=(',', ':'), sort_keys=True) 16 | if as_bytes: 17 | return bytes(s, 'utf-8') 18 | return s 19 | -------------------------------------------------------------------------------- /src/lighthouse/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-lighthouse' 8 | -------------------------------------------------------------------------------- /src/lighthouse/lighthouse-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 10 | 11 | if __name__ == '__main__': 12 | from lighthouse import cli 13 | sys.exit(cli.run(thisfile, sys.argv[1:])) 14 | -------------------------------------------------------------------------------- /src/lighthouse/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Lighthouse 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/lighthouse/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build'], 6 | ) 7 | -------------------------------------------------------------------------------- /src/lkadmin/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-admin' 8 | -------------------------------------------------------------------------------- /src/lkadmin/ariadne.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import click 8 | import tomlkit 9 | 10 | from .utils import input_str, print_note, print_header 11 | 12 | 13 | @click.group() 14 | def ariadne(): 15 | '''Adjust package autobuilder settings.''' 16 | 17 | 18 | def ariadne_set_value(key, value): 19 | from laniakea.db.core import LkModule, config_set_value 20 | 21 | config_set_value(LkModule.ARIADNE, key, value) 22 | 23 | 24 | def _set_ariadne_config(*, indep_arch_affinity: str): 25 | if indep_arch_affinity == 'all': 26 | raise Exception('Architecture affinity for arch:all can not be arch:all as well.') 27 | if not indep_arch_affinity: 28 | raise Exception('Architecture affinity can not be empty.') 29 | 30 | ariadne_set_value('indep_arch_affinity', indep_arch_affinity) 31 | 32 | 33 | @ariadne.command() 34 | def configure_all(): 35 | '''Configure this module.''' 36 | 37 | print_header('Configuring settings for Ariadne (package building)') 38 | 39 | arch_affinity = None 40 | while not arch_affinity: 41 | arch_affinity = input_str('Architecture affinity for arch:all / arch-indep packages') 42 | arch_affinity = arch_affinity.strip() if arch_affinity else None 43 | if arch_affinity == 'all': 44 | print_note('Architecture affinity for arch:all can not be arch:all as well.') 45 | arch_affinity = None 46 | 47 | _set_ariadne_config(indep_arch_affinity=arch_affinity) 48 | 49 | 50 | @ariadne.command() 51 | @click.argument('config_fname', nargs=1) 52 | def update_from_config(config_fname): 53 | '''Add/update all settings from a TOML config file.''' 54 | with open(config_fname, 'r', encoding='utf-8') as f: 55 | conf = tomlkit.load(f) 56 | 57 | _set_ariadne_config(indep_arch_affinity=conf.get('indep_arch_affinity', '')) 58 | -------------------------------------------------------------------------------- /src/lkadmin/lk-admin.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', 'lib', 'laniakea'))) 10 | if not thisfile.startswith(('/usr', '/bin')): 11 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 12 | 13 | if __name__ == '__main__': 14 | from lkadmin import cli 15 | 16 | sys.exit(cli.run(thisfile, sys.argv[1:])) 17 | -------------------------------------------------------------------------------- /src/lkadmin/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Admin CLI 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/lkadmin/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build', 'lk-admin.py'], 6 | ) 7 | install_data('lk-admin.py', install_dir: 'bin', rename: 'lk-admin') 8 | -------------------------------------------------------------------------------- /src/lkadmin/planter.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import click 8 | 9 | from .utils import input_str, print_header 10 | 11 | 12 | @click.group() 13 | def planter(): 14 | '''Configure settings for Planter (seed packages)''' 15 | 16 | 17 | @planter.command() 18 | def configure_all(): 19 | '''Configure this module.''' 20 | 21 | def planter_set_value(key, value): 22 | from laniakea.db.core import LkModule, config_set_value 23 | 24 | config_set_value(LkModule.PLANTER, key, value) 25 | 26 | print_header('Configuring settings for Planter (metapackages / germinator)') 27 | 28 | git_url = input_str('Git clone URL for the germinate metapackage sources') 29 | if git_url: 30 | planter_set_value('git_seeds_url', git_url) 31 | -------------------------------------------------------------------------------- /src/lkarchive/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2016-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-admin' 8 | -------------------------------------------------------------------------------- /src/lkarchive/lk-archive.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', 'lib', 'laniakea'))) 10 | if not thisfile.startswith(('/usr', '/bin')): 11 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 12 | 13 | if __name__ == '__main__': 14 | from lkarchive import cli 15 | 16 | sys.exit(cli.run(thisfile, sys.argv[1:])) 17 | -------------------------------------------------------------------------------- /src/lkarchive/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Archive CLI 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/lkarchive/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build', 'lk-archive.py'], 6 | ) 7 | install_data('lk-archive.py', install_dir: 'bin', rename: 'lk-archive') 8 | -------------------------------------------------------------------------------- /src/lkscheduler/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-lighthouse' 8 | -------------------------------------------------------------------------------- /src/lkscheduler/cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2020-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import sys 8 | from argparse import ArgumentParser 9 | 10 | __mainfile = None 11 | 12 | 13 | def run_server(options): 14 | from laniakea.logging import set_verbose 15 | from laniakea.utils.misc import ensure_laniakea_master_user 16 | from lkscheduler.sdaemon import SchedulerDaemon 17 | from laniakea.localconfig import LocalConfig 18 | 19 | set_verbose(options.verbose) 20 | if options.config_fname: 21 | LocalConfig(options.config_fname) 22 | 23 | # we must run as the designated master user, otherwise we might run into permission error 24 | # or, even worse, create security risks in case we run as root 25 | ensure_laniakea_master_user(warn_only=options.no_user_check) 26 | 27 | daemon = SchedulerDaemon() 28 | daemon.run() 29 | 30 | 31 | def check_print_version(options): 32 | if options.show_version: 33 | from laniakea import __version__ 34 | 35 | print(__version__) 36 | sys.exit(0) 37 | 38 | 39 | def create_parser(): 40 | """Create Laniakea Scheduler CLI argument parser""" 41 | 42 | parser = ArgumentParser(description='Archive management task scheduler') 43 | 44 | # generic arguments 45 | parser.add_argument('--verbose', action='store_true', dest='verbose', help='Enable debug messages.') 46 | parser.add_argument( 47 | '--version', action='store_true', dest='show_version', help='Display the version of Laniakea itself.' 48 | ) 49 | parser.add_argument( 50 | '--no-user-check', 51 | action='store_true', 52 | dest='no_user_check', 53 | help='Don\'t verify that we run as the right user.', 54 | ) 55 | parser.add_argument( 56 | '--config', 57 | action='store', 58 | dest='config_fname', 59 | default=None, 60 | help='Location of the base configuration file to use.', 61 | ) 62 | 63 | parser.set_defaults(func=run_server) 64 | 65 | return parser 66 | 67 | 68 | def run(mainfile, args): 69 | from laniakea.utils import set_process_title 70 | 71 | set_process_title('laniakea-scheduler') 72 | global __mainfile 73 | __mainfile = mainfile 74 | 75 | parser = create_parser() 76 | 77 | args = parser.parse_args(args) 78 | check_print_version(args) 79 | args.func(args) 80 | -------------------------------------------------------------------------------- /src/lkscheduler/laniakea-scheduler: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 10 | 11 | if __name__ == '__main__': 12 | from lkscheduler import cli 13 | sys.exit(cli.run(thisfile, sys.argv[1:])) 14 | -------------------------------------------------------------------------------- /src/lkscheduler/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Scheduler Daemon 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/lkscheduler/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build'], 6 | ) 7 | -------------------------------------------------------------------------------- /src/mailgun/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-lighthouse' 8 | -------------------------------------------------------------------------------- /src/mailgun/cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2020-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import sys 8 | import asyncio 9 | from argparse import ArgumentParser 10 | 11 | from .mailrelay import MailRelay 12 | 13 | __mainfile = None 14 | 15 | 16 | def run_relay(options): 17 | from laniakea.localconfig import LocalConfig 18 | 19 | if options.config_fname: 20 | LocalConfig(options.config_fname) 21 | 22 | if options.verbose: 23 | from laniakea.logging import set_verbose 24 | 25 | set_verbose(True) 26 | 27 | loop = asyncio.new_event_loop() 28 | asyncio.set_event_loop(loop) 29 | 30 | relay = MailRelay() 31 | try: 32 | loop.run_until_complete(relay.run()) 33 | finally: 34 | relay.stop() 35 | loop.run_until_complete(loop.shutdown_asyncgens()) 36 | loop.close() 37 | 38 | 39 | def check_print_version(options): 40 | if options.show_version: 41 | from laniakea import __version__ 42 | 43 | print(__version__) 44 | sys.exit(0) 45 | 46 | 47 | def create_parser(): 48 | """Create Laniakea Mailgun argument parser""" 49 | 50 | parser = ArgumentParser(description='E-Mail emitter') 51 | 52 | # generic arguments 53 | parser.add_argument('--verbose', action='store_true', dest='verbose', help='Enable debug messages.') 54 | parser.add_argument( 55 | '--version', action='store_true', dest='show_version', help='Display the version of Laniakea itself.' 56 | ) 57 | parser.add_argument( 58 | '--config', 59 | action='store', 60 | dest='config_fname', 61 | default=None, 62 | help='Location of the base configuration file to use.', 63 | ) 64 | 65 | parser.set_defaults(func=run_relay) 66 | 67 | return parser 68 | 69 | 70 | def run(mainfile, args): 71 | from laniakea.utils import set_process_title 72 | 73 | set_process_title('laniakea-mailgun') 74 | global __mainfile 75 | __mainfile = mainfile 76 | 77 | parser = create_parser() 78 | 79 | args = parser.parse_args(args) 80 | check_print_version(args) 81 | args.func(args) 82 | -------------------------------------------------------------------------------- /src/mailgun/laniakea-mailgun: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 10 | 11 | if __name__ == '__main__': 12 | from mailgun import cli 13 | sys.exit(cli.run(thisfile, sys.argv[1:])) 14 | -------------------------------------------------------------------------------- /src/mailgun/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Mailgun Daemon 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/mailgun/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build'], 6 | ) 7 | -------------------------------------------------------------------------------- /src/mailgun/templates/package-accepted-announce.tmpl: -------------------------------------------------------------------------------- 1 | From: {{from_address}} 2 | To: {{announce_address}} 3 | X-Laniakea-Project: {{project_name}} 4 | X-Laniakea-Repo: {{repo}} 5 | X-Laniakea-Package: {{source_name}} 6 | X-Laniakea-Event: package-accepted 7 | MIME-Version: 1.0 8 | Content-Type: text/plain; charset="utf-8" 9 | Content-Transfer-Encoding: 8bit 10 | Subject: [{{repo}}] Accepted {{source_name}} {{source_version}} into {{suite}} 11 | 12 | {{changes}} 13 | 14 | Accepted: 15 | 16 | {{ files|join('\n ') }} 17 | 18 | Thanks to {{uploader_name}} for the contribution. 19 | -------------------------------------------------------------------------------- /src/mailgun/templates/package-accepted.tmpl: -------------------------------------------------------------------------------- 1 | From: {{from_address}} 2 | To: {{uploader_email}} 3 | X-Laniakea-Project: {{project_name}} 4 | X-Laniakea-Repo: {{repo}} 5 | X-Laniakea-Package: {{source_name}} 6 | X-Laniakea-Event: package-accepted 7 | Precedence: bulk 8 | Auto-Submitted: auto-generated 9 | MIME-Version: 1.0 10 | Content-Type: text/plain; charset="utf-8" 11 | Content-Transfer-Encoding: 8bit 12 | Subject: [{{repo}}] {{upload_name}} ACCEPTED into {{suite}} 13 | 14 | Accepted {{source_name}} {{source_version}}: 15 | 16 | {{changes}} 17 | 18 | Files: 19 | 20 | {{ files|join('\n ') }} 21 | 22 | Thank you for your contribution to {{project_name}}/{{repo}}! 23 | -------------------------------------------------------------------------------- /src/mailgun/templates/package-new.tmpl: -------------------------------------------------------------------------------- 1 | From: {{from_address}} 2 | To: {{uploader_email}} 3 | X-Laniakea-Project: {{project_name}} 4 | X-Laniakea-Repo: {{repo}} 5 | X-Laniakea-Package: {{source_name}} 6 | X-Laniakea-Event: package-queued-new 7 | Precedence: bulk 8 | Auto-Submitted: auto-generated 9 | MIME-Version: 1.0 10 | Content-Type: text/plain; charset="utf-8" 11 | Content-Transfer-Encoding: 8bit 12 | Subject: [{{repo}}] {{upload_name}} for {{suite_name}} is NEW 13 | 14 | Hello! 15 | 16 | Your package has been put into the NEW queue, which means it will require 17 | a human review to proceed further. 18 | The upload was otherwise valid (it had a good OpenPGP signature and file 19 | hashes are valid), so please be patient. 20 | 21 | Packages are routinely processed through to the archive, and do feel 22 | free to browse the NEW queue[1]. 23 | 24 | If there is an issue with the upload, you will receive an email from a 25 | member of the review team. 26 | 27 | [1]: {{new_queue_url}} 28 | -------------------------------------------------------------------------------- /src/mailgun/templates/package-rejected.tmpl: -------------------------------------------------------------------------------- 1 | From: {{from_address}} 2 | To: {{uploader_email}} 3 | X-Laniakea-Project: {{project_name}} 4 | X-Laniakea-Repo: {{repo}} 5 | X-Laniakea-Event: package-rejected 6 | Precedence: bulk 7 | Auto-Submitted: auto-generated 8 | MIME-Version: 1.0 9 | Content-Type: text/plain; charset="utf-8" 10 | Content-Transfer-Encoding: 8bit 11 | Subject: [{{repo}}] {{upload_name}} REJECTED 12 | 13 | Hello! 14 | 15 | Unfortunately, your upload was rejected: 16 | {{reason}} 17 | 18 | === 19 | 20 | Please feel free to contact the archive admins or review team if you don't 21 | understand why your files were rejected. 22 | -------------------------------------------------------------------------------- /src/mirk/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-lighthouse' 8 | -------------------------------------------------------------------------------- /src/mirk/cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import sys 8 | import asyncio 9 | from argparse import ArgumentParser 10 | 11 | from .msgpublish import MatrixPublisher 12 | 13 | 14 | def run_matrix_bot(options): 15 | if options.verbose: 16 | from laniakea.logging import set_verbose 17 | 18 | set_verbose(True) 19 | 20 | loop = asyncio.new_event_loop() 21 | asyncio.set_event_loop(loop) 22 | 23 | bot_pub = MatrixPublisher() 24 | try: 25 | loop.run_until_complete(bot_pub.run()) 26 | finally: 27 | bot_pub.stop() 28 | loop.run_until_complete(loop.shutdown_asyncgens()) 29 | loop.close() 30 | 31 | 32 | def check_print_version(options): 33 | if options.show_version: 34 | from laniakea import __version__ 35 | 36 | print(__version__) 37 | sys.exit(0) 38 | 39 | 40 | def create_parser(): 41 | '''Create mIrk CLI argument parser''' 42 | 43 | parser = ArgumentParser(description='Matrix message bot') 44 | 45 | # generic arguments 46 | parser.add_argument('--verbose', action='store_true', dest='verbose', help='Enable debug messages.') 47 | parser.add_argument( 48 | '--version', action='store_true', dest='show_version', help='Display the version of Laniakea itself.' 49 | ) 50 | 51 | parser.set_defaults(func=run_matrix_bot) 52 | 53 | return parser 54 | 55 | 56 | def run(mainfile, args): 57 | from laniakea.utils import set_process_title 58 | 59 | set_process_title('laniakea-mirk') 60 | 61 | parser = create_parser() 62 | 63 | args = parser.parse_args(args) 64 | check_print_version(args) 65 | args.func(args) 66 | -------------------------------------------------------------------------------- /src/mirk/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - mIrk 2 | 3 | # Additional Python deps 4 | r = run_command(pymod_check_exe, [pymod_check_arg, 'matrix'], check: false) 5 | if r.returncode() != 0 6 | error(r.stderr().strip()) 7 | endif 8 | 9 | install_subdir('.', install_dir: 'lib/laniakea/mirk/', 10 | exclude_directories: ['__pycache__'], 11 | exclude_files: ['meson.build'], 12 | ) 13 | -------------------------------------------------------------------------------- /src/mirk/mirk: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 10 | 11 | if __name__ == '__main__': 12 | from mirk import cli 13 | sys.exit(cli.run(thisfile, sys.argv[1:])) 14 | -------------------------------------------------------------------------------- /src/planter/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Planter 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/planter/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build'], 6 | ) 7 | -------------------------------------------------------------------------------- /src/rubicon/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-rubicon' 8 | -------------------------------------------------------------------------------- /src/rubicon/cli.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import sys 8 | from argparse import ArgumentParser 9 | 10 | from .fileimport import import_files 11 | 12 | __mainfile = None 13 | 14 | 15 | def check_print_version(options): 16 | if options.show_version: 17 | from laniakea import __version__ 18 | 19 | print(__version__) 20 | sys.exit(0) 21 | 22 | 23 | def create_parser(): 24 | '''Create Rubicon CLI argument parser''' 25 | 26 | parser = ArgumentParser(description='Import artifacts into a secure area') 27 | 28 | # generic arguments 29 | parser.add_argument('--verbose', action='store_true', dest='verbose', help='Enable debug messages.') 30 | parser.add_argument( 31 | '--version', action='store_true', dest='show_version', help='Display the version of Laniakea itself.' 32 | ) 33 | parser.add_argument( 34 | '--repo', dest='repo_name', help='Act only on the repository with this name, instead of on all repositories.' 35 | ) 36 | parser.add_argument( 37 | 'incoming_dir', nargs='?', default=None, help='Override the directory of incoming files to process.' 38 | ) 39 | 40 | return parser 41 | 42 | 43 | def run(mainfile, args): 44 | from laniakea.logging import configure_pkg_archive_logger 45 | from laniakea.utils.misc import set_process_title, ensure_laniakea_master_user 46 | 47 | set_process_title('laniakea-rubicon') 48 | global __mainfile 49 | __mainfile = mainfile 50 | 51 | parser = create_parser() 52 | 53 | args = parser.parse_args(args) 54 | check_print_version(args) 55 | 56 | # ensure we run as the correct user 57 | ensure_laniakea_master_user() 58 | # configure the archive action file logging 59 | configure_pkg_archive_logger() 60 | 61 | import_files(args) 62 | -------------------------------------------------------------------------------- /src/rubicon/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Rubicon 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/rubicon/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build', 'rubicon'], 6 | ) 7 | 8 | if get_option('virtualenv') != '' 9 | vbin_data = configuration_data() 10 | vbin_data.set('LK_VIRTUALENV_DIR', get_option('virtualenv').strip()) 11 | configure_file( 12 | input: 'rubicon.in', 13 | output: 'rubicon', 14 | configuration: vbin_data, 15 | install_dir: 'bin', 16 | ) 17 | else 18 | install_data('rubicon', install_dir: 'bin', rename: 'rubicon') 19 | endif 20 | -------------------------------------------------------------------------------- /src/rubicon/rubicon: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', 'lib', 'laniakea'))) 10 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', 'lib', 'laniakea', 'rubicon'))) 11 | if not thisfile.startswith(('/usr', '/bin')): 12 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 13 | 14 | if __name__ == '__main__': 15 | from rubicon import cli 16 | sys.exit(cli.run(thisfile, sys.argv[1:])) 17 | -------------------------------------------------------------------------------- /src/rubicon/rubicon.in: -------------------------------------------------------------------------------- 1 | #!@LK_VIRTUALENV_DIR@/bin/python 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', 'lib', 'laniakea'))) 10 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', 'lib', 'laniakea', 'rubicon'))) 11 | if not thisfile.startswith(('/usr', '/bin')): 12 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 13 | 14 | if __name__ == '__main__': 15 | from rubicon import cli 16 | sys.exit(cli.run(thisfile, sys.argv[1:])) 17 | -------------------------------------------------------------------------------- /src/spears/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-spears' 8 | -------------------------------------------------------------------------------- /src/spears/britney.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | 9 | from laniakea.git import Git 10 | from laniakea.logging import get_verbose 11 | from laniakea.localconfig import LocalConfig, ExternalToolsUrls 12 | 13 | 14 | class Britney: 15 | """ 16 | Interface to Debian's Archive Migrator (Britney2) 17 | """ 18 | 19 | def __init__(self): 20 | lconf = LocalConfig() 21 | 22 | self._britney_dir = os.path.join(lconf.workspace, 'tools', 'britney2') 23 | self._britney_exe = os.path.join(self._britney_dir, 'britney.py') 24 | 25 | def update_dist(self): 26 | ext_urls = ExternalToolsUrls() 27 | 28 | git = Git() 29 | git.location = self._britney_dir 30 | if os.path.isdir(os.path.join(self._britney_dir, '.git')): 31 | git.pull() 32 | else: 33 | os.makedirs(self._britney_dir, exist_ok=True) 34 | git.clone(ext_urls.britney_git_repository) 35 | 36 | def run(self, wdir, config_fname, args: list[str] = None): 37 | from laniakea.utils import run_forwarded 38 | 39 | if not args: 40 | args = [] 41 | 42 | # automatically fetch Britney if it doesn't exist yet 43 | if not os.path.isfile(self._britney_exe): 44 | self.update_dist() 45 | 46 | cmd = [self._britney_exe] 47 | cmd.extend(['-c', config_fname]) 48 | cmd.extend(args) 49 | 50 | out, ret = run_forwarded(cmd, cwd=wdir, print_output=get_verbose()) 51 | if ret != 0: 52 | raise Exception('Britney run failed: {}'.format(out)) 53 | 54 | return out 55 | -------------------------------------------------------------------------------- /src/spears/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Spears 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/spears/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build'], 6 | ) 7 | -------------------------------------------------------------------------------- /src/spears/spears: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 10 | 11 | if __name__ == '__main__': 12 | from spears import cli 13 | sys.exit(cli.run(thisfile, sys.argv[1:])) 14 | -------------------------------------------------------------------------------- /src/synchrotron/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | __appname__ = 'laniakea-synchrotron' 8 | -------------------------------------------------------------------------------- /src/synchrotron/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Synchrotron 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/synchrotron/', 4 | exclude_directories: ['__pycache__'], 5 | exclude_files: ['meson.build', 'synchrotron'], 6 | ) 7 | install_data('synchrotron', install_dir: 'bin', rename: 'synchrotron') 8 | -------------------------------------------------------------------------------- /src/synchrotron/synchrotron: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | 6 | thisfile = __file__ 7 | if not os.path.isabs(thisfile): 8 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 9 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', 'lib', 'laniakea'))) 10 | if not thisfile.startswith(('/usr', '/bin')): 11 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..'))) 12 | 13 | if __name__ == '__main__': 14 | from synchrotron import cli 15 | sys.exit(cli.run(thisfile, sys.argv[1:])) 16 | -------------------------------------------------------------------------------- /src/webdash/lkweb/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | import sys 9 | 10 | # ensure the Laniakea Python module is found 11 | thisfile = __file__ 12 | if not os.path.isabs(thisfile): 13 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 14 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', '..'))) 15 | 16 | 17 | from .app import create_app 18 | 19 | __all__ = ['create_app'] 20 | -------------------------------------------------------------------------------- /src/webdash/lkweb/api/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .api import rebar 4 | 5 | __all__ = ['rebar'] 6 | -------------------------------------------------------------------------------- /src/webdash/lkweb/config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | 9 | # Instance folder path 10 | INSTANCE_FOLDER_PATH = '/var/lib/laniakea/webdash/' 11 | 12 | 13 | class BaseConfig: 14 | PROJECT = 'Laniakea Web Dashboard' 15 | BUG_REPORT_URL = 'https://github.com/lkhq/laniakea/issues' 16 | 17 | LOG_STORAGE_URL = '/metadata/logs' # web URL where raw logs are stored by Rubicon 18 | 19 | # 20 | # Caching behavior 21 | # 22 | CACHE_TYPE = 'simple' 23 | CACHE_DEFAULT_TIMEOUT = 300 24 | 25 | # Get app root path, also can use flask.root_path. 26 | # ../../config.py 27 | PROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 28 | 29 | DEBUG = False 30 | TESTING = False 31 | 32 | # http://flask.pocoo.org/docs/quickstart/#sessions 33 | SECRET_KEY = 'secret key' 34 | 35 | LOG_FOLDER = os.path.join(INSTANCE_FOLDER_PATH, 'logs') 36 | 37 | THEME = 'default' 38 | 39 | 40 | class DefaultConfig(BaseConfig): 41 | DEBUG = False 42 | CACHE_TYPE = 'simple' 43 | 44 | 45 | class DebugConfig(BaseConfig): 46 | DEBUG = True 47 | CACHE_TYPE = 'null' 48 | -------------------------------------------------------------------------------- /src/webdash/lkweb/decorators.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from functools import wraps 8 | 9 | from flask import abort 10 | from flask_login import current_user 11 | 12 | 13 | def admin_required(f): 14 | @wraps(f) 15 | def decorated_function(*args, **kwargs): 16 | if not current_user.is_admin(): 17 | abort(403) 18 | return f(*args, **kwargs) 19 | 20 | return decorated_function 21 | -------------------------------------------------------------------------------- /src/webdash/lkweb/depcheck/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import depcheck 4 | 5 | __all__ = ['depcheck'] 6 | -------------------------------------------------------------------------------- /src/webdash/lkweb/extensions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from flask_login import LoginManager 8 | from flask_caching import Cache 9 | 10 | login_manager = LoginManager() 11 | 12 | cache = Cache() 13 | -------------------------------------------------------------------------------- /src/webdash/lkweb/jobs/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import jobs 4 | 5 | __all__ = ['jobs'] 6 | -------------------------------------------------------------------------------- /src/webdash/lkweb/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import migrations 4 | 5 | __all__ = ['migrations'] 6 | -------------------------------------------------------------------------------- /src/webdash/lkweb/osimages/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import osimages 4 | 5 | __all__ = ['osimages'] 6 | -------------------------------------------------------------------------------- /src/webdash/lkweb/osimages/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from flask import Blueprint, render_template 8 | 9 | from laniakea.db import Job, JobResult, ImageFormat, ImageBuildRecipe, session_scope 10 | 11 | from ..utils import humanized_timediff 12 | 13 | osimages = Blueprint('osimages', __name__, url_prefix='/osimages') 14 | 15 | 16 | def last_jobs_for_recipe(session, recipe): 17 | return session.query(Job).filter(Job.trigger == recipe.uuid).order_by(Job.time_created.desc()).slice(0, 4).all() 18 | 19 | 20 | @osimages.route('/') 21 | def index(): 22 | with session_scope() as session: 23 | recipes = ( 24 | session.query(ImageBuildRecipe).order_by(ImageBuildRecipe.suite.desc(), ImageBuildRecipe.name.desc()).all() 25 | ) 26 | 27 | return render_template( 28 | 'osimages/index.html', 29 | session=session, 30 | last_jobs_for_recipe=last_jobs_for_recipe, 31 | humanized_timediff=humanized_timediff, 32 | ImageFormat=ImageFormat, 33 | JobResult=JobResult, 34 | recipes=recipes, 35 | ) 36 | -------------------------------------------------------------------------------- /src/webdash/lkweb/overview/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import overview 4 | 5 | __all__ = ['overview'] 6 | -------------------------------------------------------------------------------- /src/webdash/lkweb/review_queues/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import review_queues 4 | 5 | __all__ = ['review_queues'] 6 | -------------------------------------------------------------------------------- /src/webdash/lkweb/synchronization/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import synchronization 4 | 5 | __all__ = ['synchronization'] 6 | -------------------------------------------------------------------------------- /src/webdash/lkweb/synchronization/views.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from flask import Blueprint, abort, render_template 8 | 9 | from laniakea.db import ( 10 | ArchiveSuite, 11 | SynchrotronIssue, 12 | SynchrotronConfig, 13 | SyncBlacklistEntry, 14 | SynchrotronIssueKind, 15 | session_scope, 16 | ) 17 | 18 | from ..extensions import cache 19 | 20 | synchronization = Blueprint('synchronization', __name__, url_prefix='/sync') 21 | 22 | 23 | @synchronization.route('/') 24 | @cache.cached(timeout=60 * 10) 25 | def index(): 26 | with session_scope() as session: 27 | sync_configs = ( 28 | session.query(SynchrotronConfig).join(SynchrotronConfig.destination_suite).order_by(ArchiveSuite.name).all() 29 | ) 30 | 31 | auto_syncs = [] 32 | manual_syncs = [] 33 | for sc in sync_configs: 34 | if sc.sync_auto_enabled: 35 | auto_syncs.append(sc) 36 | else: 37 | manual_syncs.append(sc) 38 | 39 | return render_template('synchronization/index.html', auto_syncs=auto_syncs, manual_syncs=manual_syncs) 40 | 41 | 42 | @synchronization.route('/issues') 43 | def issues_table(config_id: int): 44 | with session_scope() as session: 45 | sync_config = session.query(SynchrotronConfig).filter(SynchrotronConfig.id == config_id).one_or_none() 46 | if not sync_config: 47 | abort(404) 48 | issues = session.query(SynchrotronIssue).filter(SynchrotronIssue.config_id == sync_config.id).all() 49 | 50 | return render_template( 51 | 'synchronization/sync_issue_table.html', 52 | issues=issues, 53 | SyncIssueKind=SynchrotronIssueKind, 54 | sconf=sync_config, 55 | ) 56 | 57 | 58 | @synchronization.route('/blacklist/') 59 | def blacklist(config_id: int): 60 | with session_scope() as session: 61 | sync_config = session.query(SynchrotronConfig).filter(SynchrotronConfig.id == config_id).one_or_none() 62 | if not sync_config: 63 | abort(404) 64 | entries = session.query(SyncBlacklistEntry).filter(SyncBlacklistEntry.config_id == sync_config.id).all() 65 | 66 | return render_template('synchronization/blacklist.html', entries=entries, sconf=sync_config) 67 | -------------------------------------------------------------------------------- /src/webdash/lkweb/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import re 8 | from datetime import datetime 9 | 10 | import humanize 11 | from sqlalchemy import func 12 | 13 | import laniakea.typing as T 14 | from laniakea.db import StatsEntry 15 | 16 | UUID_RE = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') 17 | 18 | 19 | def is_uuid(value): 20 | ''' 21 | Quickly check if :value is a UUID. 22 | ''' 23 | return True if UUID_RE.match(value) else False 24 | 25 | 26 | def humanized_timediff(time): 27 | ''' 28 | Get a time difference of :time with the current clock time 29 | in a human-readable format. 30 | ''' 31 | if not time: 32 | return 'Never' 33 | 34 | timediff = datetime.utcnow().replace(microsecond=0) - time 35 | return humanize.naturaltime(timediff) 36 | 37 | 38 | def fetch_statistics_for(session, stat_key: str, start_at: datetime) -> list[dict[str, T.Any]] | None: 39 | values = ( 40 | session.query(func.extract('epoch', StatsEntry.time), StatsEntry.value) 41 | .filter(StatsEntry.key == stat_key, StatsEntry.time > start_at) 42 | .order_by(StatsEntry.time) 43 | .all() 44 | ) 45 | if not values: 46 | return None 47 | return [{'x': int(v[0]), 'y': v[1]} for v in values] 48 | -------------------------------------------------------------------------------- /src/webdash/lkwebdash.ini.in: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | plugin = python3 3 | wsgi-file = wsgi.py 4 | 5 | master = true 6 | processes = 5 7 | 8 | socket = /run/laniakea-webdash/webdash.sock 9 | chmod-socket = 660 10 | vacuum = true 11 | 12 | die-on-term = true 13 | need-app = true 14 | @LK_VIRTUALENV_HOME_ENTRY@ 15 | -------------------------------------------------------------------------------- /src/webdash/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Web Dashboard UI 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/webdash/', 4 | exclude_directories: ['__pycache__', 'lkweb/__pycache__'], 5 | exclude_files: ['meson.build', '.gitignore', 'lkwebdash.ini.in'], 6 | ) 7 | 8 | wd_data = configuration_data() 9 | wd_data.set('LK_VIRTUALENV_HOME_ENTRY', '') 10 | if get_option('virtualenv') != '' 11 | wd_data.set('LK_VIRTUALENV_HOME_ENTRY', 'home = ' + get_option('virtualenv').strip()) 12 | endif 13 | 14 | configure_file( 15 | input: 'lkwebdash.ini.in', 16 | output: 'lkwebdash.ini', 17 | configuration: wd_data, 18 | install_dir: 'lib/laniakea/webdash/', 19 | ) 20 | -------------------------------------------------------------------------------- /src/webdash/run-devel.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | BASEDIR=$(dirname "$0") 5 | cd $BASEDIR 6 | 7 | export FLASK_DEBUG=1 8 | export FLASK_ENV=development 9 | exec flask run --with-threads $@ 10 | -------------------------------------------------------------------------------- /src/webdash/templates/default/.gitignore: -------------------------------------------------------------------------------- 1 | static/css/fontawesome/ 2 | static/css/webfonts/ 3 | static/css/bulma*.css 4 | static/js/jquery/ 5 | static/js/chart/ 6 | static/js/moment/ 7 | static/fonts/ 8 | -------------------------------------------------------------------------------- /src/webdash/templates/default/depcheck/layout.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set active_menu = 'depcheck' %} 4 | 5 | {% block breadcrumbs %} 6 | 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /src/webdash/templates/default/errors/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found - {{ config.PROJECT }} 6 | 7 | 44 | 45 | 46 |

Page Not Found

47 |

Sorry, but the page you were trying to view does not exist.

48 | 49 | 50 | -------------------------------------------------------------------------------- /src/webdash/templates/default/errors/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Internal Error - {{ config.PROJECT }} 6 | 7 | 44 | 45 | 46 |

Internal Error

47 |

Sorry, there was an internal error.

48 |

The problem very likely is on our side and there is nothing you can do about it. If this issue persists, please file a bug report.

49 | 50 | 51 | -------------------------------------------------------------------------------- /src/webdash/templates/default/jobs/job_osimage.html: -------------------------------------------------------------------------------- 1 | {% extends 'jobs/job_generic.html' %} 2 | 3 | {% block job_details %} 4 | {% if not recipe %} 5 |
6 | Unable to find an image recipe for this job! 7 | The recipe might have been removed and is no longer available. 8 |
9 | {% else %} 10 | 11 |

Details

12 |

13 | Distribution: {{recipe.distribution}}
14 | Suite: {{recipe.suite}}
15 | Environment: {{recipe.environment}}
16 | Style: {{recipe.style}}
17 | Architecture: {{job.architecture}}
18 |

19 | 20 | {% endif %} 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /src/webdash/templates/default/jobs/workers.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set active_menu = 'workers' %} 4 | {% set page_title = 'Workers' %} 5 | 6 | {% block body_header %} 7 |

Spark Workers

8 | {% endblock %} 9 | 10 | {% block body %} 11 | 12 |
13 |
14 | 15 | {% for worker in workers %} 16 | 31 | {% endfor %} 32 | 33 |
34 |
35 | 36 | {% endblock %} 37 | -------------------------------------------------------------------------------- /src/webdash/templates/default/migrations/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'migrations/layout.html' %} 2 | 3 | {% set page_title = 'Package Migrations' %} 4 | 5 | {% block body_header %} 6 |

Package Migration Excuses

7 | {% endblock %} 8 | 9 | {% block body %} 10 |
11 |
12 | 13 | {% for repo_name, mtasks in migrations.items() %} 14 |

Repository: {{repo_name}}

15 | {% for m in mtasks %} 16 | 20 | {{m.from}}  {{m.to}} 21 | 22 |
23 | {% endfor %} 24 | {% endfor %} 25 | 26 |
27 |
28 | {% endblock %} 29 | -------------------------------------------------------------------------------- /src/webdash/templates/default/migrations/layout.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set active_menu = 'migrations' %} 4 | 5 | {% block breadcrumbs %} 6 | 26 | {% endblock %} 27 | -------------------------------------------------------------------------------- /src/webdash/templates/default/osimages/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set active_menu = 'osimages' %} 4 | {% set page_title = 'OS Image Recipes' %} 5 | 6 | {% block body_header %} 7 |

OS Image Recipes

8 | {% endblock %} 9 | 10 | {% block body %} 11 |
12 |
13 | 14 | {% for recipe in recipes %} 15 | 40 | {% endfor %} 41 | 42 |
43 |
44 | {% endblock %} 45 | -------------------------------------------------------------------------------- /src/webdash/templates/default/review_queues/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set active_menu = 'reviewqueues' %} 4 | {% set page_title = 'Review Queues' %} 5 | 6 | {% block breadcrumbs %} 7 | 17 | {% endblock %} 18 | 19 | {% block body_header %} 20 |

Review Queues

21 | {% endblock %} 22 | 23 | {% block body %} 24 | 25 |
26 |
27 | 28 | {% for queue in new_queues %} 29 |

NEW queue for {{queue.rss.repo.name}}/{{queue.rss.suite.name}}

30 | 31 | {% if not queue.entries %} 32 |
33 |
34 |

This queue is empty!

35 |
36 |
37 | {% else %} 38 | 39 | {% for entry in queue.entries %} 40 |
41 |
42 |
43 | {{entry.spkg.name}} {{entry.spkg.version}} ↠ {{entry.info.destination.name}}/{{entry.spkg.component.name}} 44 | 45 |  {{entry.spkg.architectures|join(' ')}} 46 |  {{humanized_timediff(entry.spkg.time_added)}} 47 |
48 |
49 |
50 | {% endfor %} 51 | 52 | {% endif %} 53 | {% endfor %} 54 |
55 |
56 | {% endblock %} 57 | -------------------------------------------------------------------------------- /src/webdash/templates/default/static/js/laniakea.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | $('#side-menu').metisMenu(); 4 | 5 | }); 6 | 7 | //Loads the correct sidebar on window load, 8 | //collapses the sidebar on window resize. 9 | // Sets the min-height of #page-wrapper to window size 10 | $(function() { 11 | $(window).bind("load resize", function() { 12 | topOffset = 50; 13 | width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width; 14 | if (width < 768) { 15 | $('div.navbar-collapse').addClass('collapse'); 16 | topOffset = 100; // 2-row-menu 17 | } else { 18 | $('div.navbar-collapse').removeClass('collapse'); 19 | } 20 | 21 | height = ((this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height) - 1; 22 | height = height - topOffset; 23 | if (height < 1) height = 1; 24 | if (height > topOffset) { 25 | $("#page-wrapper").css("min-height", (height) + "px"); 26 | } 27 | }); 28 | 29 | var url = window.location; 30 | var element = $('ul.nav a').filter(function() { 31 | return this.href == url || url.href.indexOf(this.href) == 0; 32 | }).addClass('active').parent().parent().addClass('in').parent(); 33 | if (element.is('li')) { 34 | element.addClass('active'); 35 | } 36 | }); 37 | -------------------------------------------------------------------------------- /src/webdash/templates/default/synchronization/blacklist.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set active_menu = 'synchronization' %} 4 | {% set page_title = 'Synchronization Blacklist' %} 5 | 6 | {% block breadcrumbs %} 7 | 26 | {% endblock %} 27 | 28 | {% block body_header %} 29 |

Packages Prevented From Synchronization

30 | {% endblock %} 31 | 32 | {% block body %} 33 | {% if not entries %} 34 |
35 |
36 |

Any package is permitted to enter the destination suite.

37 |
38 |
39 | {% else %} 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {% for entry in entries %} 51 | 52 | 53 | 54 | 55 | 56 | {% endfor %} 57 | 58 |
PackageReasonDate
{{entry.pkgname}}{{entry.reason}}{{ entry.time_created.strftime('%Y-%m-%d %H:%M %z') if entry.time_created else 'Unknown' }}
59 | 60 | {% endif %} 61 | {% endblock %} 62 | -------------------------------------------------------------------------------- /src/webdash/wsgi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import sys 5 | 6 | BASE_DIR = os.path.join(os.path.dirname(__file__)) 7 | if BASE_DIR not in sys.path: 8 | sys.path.append(BASE_DIR) 9 | 10 | from lkweb import create_app 11 | 12 | application = create_app() 13 | -------------------------------------------------------------------------------- /src/webswview/lkswview/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | import sys 9 | 10 | # ensure the Laniakea Python module is found 11 | thisfile = __file__ 12 | if not os.path.isabs(thisfile): 13 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 14 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', '..'))) 15 | 16 | 17 | from .app import create_app 18 | 19 | __all__ = ['create_app'] 20 | -------------------------------------------------------------------------------- /src/webswview/lkswview/api/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .api import rebar 4 | 5 | __all__ = ['rebar'] 6 | -------------------------------------------------------------------------------- /src/webswview/lkswview/api/api.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from flask_rebar import Rebar, SwaggerV3Generator 8 | from marshmallow import Schema, fields 9 | 10 | rebar = Rebar() 11 | 12 | # All handler URL rules will be prefixed by '/v1' 13 | registry = rebar.create_handler_registry( 14 | prefix='/api/v1', 15 | spec_path='/apidocs', 16 | swagger_ui_path='/apidocs/ui', 17 | swagger_generator=SwaggerV3Generator(title='Laniakea SW API'), 18 | ) 19 | 20 | 21 | class TodoSchema(Schema): 22 | id = fields.Integer() 23 | complete = fields.Boolean() 24 | description = fields.String() 25 | 26 | 27 | # This schema will validate the incoming request's query string 28 | class GetTodosQueryStringSchema(Schema): 29 | complete = fields.Boolean() 30 | 31 | 32 | # This schema will marshal the outgoing response 33 | class GetTodosResponseSchema(Schema): 34 | data = fields.Nested(TodoSchema, many=True) 35 | 36 | 37 | @registry.handles( 38 | rule='/todos', 39 | method='GET', 40 | query_string_schema=GetTodosQueryStringSchema(), 41 | response_body_schema=GetTodosResponseSchema(), # for versions <= 1.7.0, use marshal_schema 42 | ) 43 | def get_todos(): 44 | """ 45 | This docstring will be rendered as the operation's description in 46 | the auto-generated OpenAPI specification. 47 | """ 48 | 49 | # The response will be marshaled by `marshal_schema` 50 | return {'data': []} 51 | -------------------------------------------------------------------------------- /src/webswview/lkswview/config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | 9 | from laniakea import LocalConfig 10 | from laniakea.db import config_get_project_name 11 | 12 | # Instance folder path 13 | INSTANCE_FOLDER_PATH = '/var/lib/laniakea/webswview/' 14 | 15 | 16 | class BaseConfig: 17 | PROJECT = 'Laniakea SWV' 18 | BUG_REPORT_URL = 'https://github.com/lkhq/laniakea/issues' 19 | 20 | OS_NAME = config_get_project_name() 21 | 22 | WEBDASH_URL = '' # Web URL to a laniakea-webdash instance. 23 | APPSTREAM_MEDIA_URL = LocalConfig().archive_appstream_media_url 24 | ARCHIVE_URL = LocalConfig().archive_url 25 | 26 | # 27 | # Caching behavior 28 | # 29 | CACHE_TYPE = 'simple' 30 | CACHE_DEFAULT_TIMEOUT = 300 31 | 32 | # Get app root path, also can use flask.root_path. 33 | # ../../config.py 34 | PROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 35 | 36 | SECRET_KEY = os.urandom(16) 37 | 38 | DEBUG = False 39 | TESTING = False 40 | 41 | LOG_FOLDER = os.path.join(INSTANCE_FOLDER_PATH, 'logs') 42 | 43 | THEME = 'default' 44 | 45 | 46 | class DefaultConfig(BaseConfig): 47 | DEBUG = False 48 | TESTING = False 49 | CACHE_TYPE = 'simple' 50 | 51 | 52 | class DebugConfig(BaseConfig): 53 | DEBUG = True 54 | TESTING = True 55 | CACHE_TYPE = 'null' 56 | -------------------------------------------------------------------------------- /src/webswview/lkswview/decorators.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from functools import wraps 8 | 9 | from flask import abort 10 | from flask_login import current_user 11 | 12 | 13 | def admin_required(f): 14 | @wraps(f) 15 | def decorated_function(*args, **kwargs): 16 | if not current_user.is_admin(): 17 | abort(403) 18 | return f(*args, **kwargs) 19 | 20 | return decorated_function 21 | -------------------------------------------------------------------------------- /src/webswview/lkswview/extensions.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from flask_caching import Cache 8 | 9 | cache = Cache() 10 | -------------------------------------------------------------------------------- /src/webswview/lkswview/packages/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import packages 4 | 5 | __all__ = ['packages'] 6 | -------------------------------------------------------------------------------- /src/webswview/lkswview/portal/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import portal 4 | 5 | __all__ = ['portal'] 6 | -------------------------------------------------------------------------------- /src/webswview/lkswview/software/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import software 4 | 5 | __all__ = ['software'] 6 | -------------------------------------------------------------------------------- /src/webswview/lkswview/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import re 8 | from datetime import datetime 9 | 10 | import humanize 11 | 12 | UUID_RE = re.compile(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$') 13 | 14 | 15 | def is_uuid(value): 16 | ''' 17 | Quickly check if :value is a UUID. 18 | ''' 19 | return True if UUID_RE.match(value) else False 20 | 21 | 22 | def humanized_timediff(time): 23 | ''' 24 | Get a time difference of _time with the current clock time 25 | in a human-readable format. 26 | ''' 27 | if not time: 28 | return 'Never' 29 | 30 | timediff = datetime.utcnow().replace(microsecond=0) - time 31 | return humanize.naturaltime(timediff) 32 | -------------------------------------------------------------------------------- /src/webswview/lkwebswview.ini.in: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | plugin = python3 3 | wsgi-file = wsgi.py 4 | 5 | master = true 6 | processes = 5 7 | 8 | socket = /run/laniakea-webswview/webswview.sock 9 | chmod-socket = 660 10 | vacuum = true 11 | 12 | die-on-term = true 13 | need-app = true 14 | @LK_VIRTUALENV_HOME_ENTRY@ 15 | -------------------------------------------------------------------------------- /src/webswview/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Web UI 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/webswview/', 4 | exclude_directories: ['__pycache__', 'lkweb/__pycache__'], 5 | exclude_files: ['meson.build', 6 | 'lkwebswview.ini.in', 7 | 'templates/default/.gitignore', 8 | 'templates/pureos/.gitignore'], 9 | ) 10 | 11 | wsw_data = configuration_data() 12 | wsw_data.set('LK_VIRTUALENV_HOME_ENTRY', '') 13 | if get_option('virtualenv') != '' 14 | wsw_data.set('LK_VIRTUALENV_HOME_ENTRY', 'home = ' + get_option('virtualenv').strip()) 15 | endif 16 | 17 | configure_file( 18 | input: 'lkwebswview.ini.in', 19 | output: 'lkwebswview.ini', 20 | configuration: wsw_data, 21 | install_dir: 'lib/laniakea/webswview/', 22 | ) 23 | -------------------------------------------------------------------------------- /src/webswview/run-devel.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | BASEDIR=$(dirname "$0") 5 | cd $BASEDIR 6 | 7 | export FLASK_DEBUG=1 8 | export FLASK_ENV=development 9 | exec flask run --with-threads $@ 10 | -------------------------------------------------------------------------------- /src/webswview/templates/default/.gitignore: -------------------------------------------------------------------------------- 1 | static/css/fontawesome/ 2 | static/css/webfonts/ 3 | static/css/bulma*.css 4 | static/js/jquery/ 5 | static/js/chart/ 6 | static/js/moment/ 7 | static/fonts/ 8 | -------------------------------------------------------------------------------- /src/webswview/templates/default/categories_index.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set page_title = 'Software categories' %} 4 | 5 | {% block body_header %} 6 |

Software categories

7 | {% endblock %} 8 | 9 | {% block breadcrumbs %} 10 | 22 | {% endblock %} 23 | 24 | {% block body %} 25 | 51 | 52 | {% endblock %} 53 | -------------------------------------------------------------------------------- /src/webswview/templates/default/errors/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Page Not Found - {{ config.PROJECT }} 6 | 7 | 44 | 45 | 46 |

Page Not Found

47 |

Sorry, but the page you were trying to view does not exist.

48 | 49 | 50 | -------------------------------------------------------------------------------- /src/webswview/templates/default/errors/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Internal Error - {{ config.PROJECT }} 6 | 7 | 44 | 45 | 46 |

Internal Error

47 |

Sorry, there was an internal error.

48 |

The problem very likely is on our side and there is nothing you can do about it. If this issue persists, please file a bug report.

49 | 50 | 51 | -------------------------------------------------------------------------------- /src/webswview/templates/default/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set page_title = 'Overview' %} 4 | 5 | {% block body_header %} 6 | 7 |
8 |
9 |
10 |

{{ config.PROJECT }} Software

11 | 12 |

Welcome to {{ config.PROJECT }} software search!

13 |
14 |
15 |
16 | 17 | 18 |
19 | 26 |
27 | {% endblock %} 28 | 29 | {% block body %} 30 | 31 | 32 | {% endblock %} 33 | -------------------------------------------------------------------------------- /src/webswview/templates/default/sections_index.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set page_title = 'Sections in ' + repo_suite.suite.name %} 4 | 5 | {% block body_header %} 6 | 7 | {% endblock %} 8 | 9 | {% block breadcrumbs %} 10 | 23 | {% endblock %} 24 | 25 | {% block body %} 26 | 27 |
28 |
29 |

Sections in {{repo_suite.suite.name}}

30 |
31 | 42 | 43 |
44 |
45 | 46 | {% for section in sections %} 47 | 59 | {% endfor %} 60 | 61 |
62 | 63 | {% endblock %} 64 | -------------------------------------------------------------------------------- /src/webswview/templates/default/static/img/app-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/webswview/templates/default/static/img/categories/applications-education.svg: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /src/webswview/templates/default/static/img/categories/applications-internet.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/webswview/templates/pureos/.gitignore: -------------------------------------------------------------------------------- 1 | static/css/fontawesome/ 2 | static/css/webfonts/ 3 | static/css/bulma*.css 4 | static/js/jquery/ 5 | static/js/chart/ 6 | static/js/moment/ 7 | static/fonts/ 8 | -------------------------------------------------------------------------------- /src/webswview/templates/pureos/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'layouts/base.html' %} 2 | 3 | {% set page_title = 'Overview' %} 4 | 5 | {% block body_header %} 6 | 7 |
8 |
9 |
10 |

PureOS Store

11 | 12 |
13 |
14 |
15 | 16 | 17 |
18 | 25 |
26 | {% endblock %} 27 | 28 | {% block body %} 29 | 30 | 31 | {% endblock %} 32 | -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/css/laniakea_swview.css: -------------------------------------------------------------------------------- 1 | ../../../default/static/css/laniakea_swview.css -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/app-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/apps-on-device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/src/webswview/templates/pureos/static/img/apps-on-device.png -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-development.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-development.svg -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-education.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-education.svg -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-games.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-games.svg -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-graphics.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-graphics.svg -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-internet.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-internet.svg -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-multimedia.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-multimedia.svg -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-office.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-office.svg -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-science.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-science.svg -------------------------------------------------------------------------------- /src/webswview/templates/pureos/static/img/categories/applications-utilities.svg: -------------------------------------------------------------------------------- 1 | ../../../../default/static/img/categories/applications-utilities.svg -------------------------------------------------------------------------------- /src/webswview/wsgi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import sys 5 | 6 | BASE_DIR = os.path.join(os.path.dirname(__file__)) 7 | if BASE_DIR not in sys.path: 8 | sys.path.append(BASE_DIR) 9 | 10 | from lkswview import create_app 11 | 12 | application = create_app() 13 | -------------------------------------------------------------------------------- /src/webupload/lkwebupload.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | plugin = python3 3 | wsgi-file = wsgi.py 4 | 5 | master = true 6 | processes = 3 7 | 8 | socket = /run/laniakea-upload/webupload.sock 9 | chmod-socket = 660 10 | vacuum = true 11 | route-run = fixpathinfo: 12 | 13 | die-on-term = true 14 | need-app = true 15 | -------------------------------------------------------------------------------- /src/webupload/lkwebupload/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | import sys 9 | 10 | # ensure the Laniakea Python module is found 11 | thisfile = __file__ 12 | if not os.path.isabs(thisfile): 13 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 14 | sys.path.append(os.path.normpath(os.path.join(os.path.dirname(thisfile), '..', '..'))) 15 | 16 | 17 | from .app import create_app 18 | 19 | __all__ = ['create_app'] 20 | -------------------------------------------------------------------------------- /src/webupload/lkwebupload/config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | 9 | # Instance folder path 10 | INSTANCE_FOLDER_PATH = '/var/lib/laniakea/webupload/' 11 | 12 | 13 | class BaseConfig: 14 | PROJECT = 'Laniakea HTTP Upload Receiver' 15 | BUG_REPORT_URL = 'https://github.com/lkhq/laniakea/issues' 16 | 17 | # Get app root path, also can use flask.root_path. 18 | # ../../config.py 19 | PROJECT_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 20 | 21 | DEBUG = False 22 | TESTING = False 23 | 24 | # http://flask.pocoo.org/docs/quickstart/#sessions 25 | SECRET_KEY = 'secret key' 26 | 27 | LOG_FOLDER = os.path.join(INSTANCE_FOLDER_PATH, 'logs') 28 | 29 | UPLOAD_CHUNK_SIZE = 4096 30 | 31 | 32 | class DefaultConfig(BaseConfig): 33 | DEBUG = False 34 | 35 | 36 | class DebugConfig(BaseConfig): 37 | DEBUG = True 38 | -------------------------------------------------------------------------------- /src/webupload/lkwebupload/upload/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from .views import upload 4 | 5 | __all__ = ['upload'] 6 | -------------------------------------------------------------------------------- /src/webupload/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea - Web Dashboard UI 2 | 3 | install_subdir('.', install_dir: 'lib/laniakea/webupload/', 4 | exclude_directories: ['__pycache__', 'lkwebupload/__pycache__'], 5 | exclude_files: ['meson.build', '.gitignore'], 6 | ) 7 | -------------------------------------------------------------------------------- /src/webupload/run-devel.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | BASEDIR=$(dirname "$0") 5 | cd $BASEDIR 6 | 7 | export FLASK_DEBUG=1 8 | export FLASK_ENV=development 9 | exec flask run --with-threads $@ 10 | -------------------------------------------------------------------------------- /src/webupload/wsgi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import sys 5 | 6 | BASE_DIR = os.path.join(os.path.dirname(__file__)) 7 | if BASE_DIR not in sys.path: 8 | sys.path.append(BASE_DIR) 9 | 10 | from lkwebupload import create_app 11 | 12 | application = create_app() 13 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | import os 8 | import sys 9 | 10 | thisfile = __file__ 11 | if not os.path.isabs(thisfile): 12 | thisfile = os.path.normpath(os.path.join(os.getcwd(), thisfile)) 13 | source_root = os.path.normpath(os.path.join(os.path.dirname(thisfile), '..')) 14 | sys.path.append(os.path.normpath(os.path.join(source_root, 'src'))) 15 | 16 | 17 | pytest_plugins = ("tests.plugins.pytest_podman",) 18 | 19 | 20 | __all__ = ['source_root', 'pytest_plugins'] 21 | -------------------------------------------------------------------------------- /tests/ci/Dockerfile-debian-stable: -------------------------------------------------------------------------------- 1 | # 2 | # Docker file for Laniakea CI 3 | # 4 | FROM debian:bookworm 5 | 6 | # prepare 7 | RUN mkdir -p /build/ci/ 8 | 9 | # install build dependencies 10 | COPY install-native-deps.sh /build/ci/ 11 | RUN chmod +x /build/ci/install-native-deps.sh && /build/ci/install-native-deps.sh 12 | 13 | # Podman within podman config 14 | COPY containers.conf /etc/containers/ 15 | RUN chmod 644 /etc/containers/containers.conf 16 | ENV _CONTAINERS_USERNS_CONFIGURED="" 17 | 18 | COPY storage.conf /etc/containers/ 19 | RUN chmod 644 /etc/containers/storage.conf 20 | 21 | VOLUME /var/lib/containers 22 | RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock 23 | 24 | # finish 25 | WORKDIR /build 26 | -------------------------------------------------------------------------------- /tests/ci/Dockerfile-debian-testing: -------------------------------------------------------------------------------- 1 | # 2 | # Docker file for Laniakea CI 3 | # 4 | FROM debian:testing 5 | 6 | # prepare 7 | RUN mkdir -p /build/ci/ 8 | 9 | # install build dependencies 10 | COPY install-native-deps.sh /build/ci/ 11 | RUN chmod +x /build/ci/install-native-deps.sh && /build/ci/install-native-deps.sh 12 | RUN eatmydata apt-get install -yq --no-install-recommends systemd-dev 13 | 14 | # Podman within podman config 15 | COPY containers.conf /etc/containers/ 16 | RUN chmod 644 /etc/containers/containers.conf 17 | ENV _CONTAINERS_USERNS_CONFIGURED="" 18 | 19 | COPY storage.conf /etc/containers/ 20 | RUN chmod 644 /etc/containers/storage.conf 21 | 22 | VOLUME /var/lib/containers 23 | RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers /var/lib/shared/vfs-images /var/lib/shared/vfs-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock; touch /var/lib/shared/vfs-images/images.lock; touch /var/lib/shared/vfs-layers/layers.lock 24 | 25 | # finish 26 | WORKDIR /build 27 | -------------------------------------------------------------------------------- /tests/ci/README.md: -------------------------------------------------------------------------------- 1 | # Continuous Integration Environment Construction 2 | This is the continuous integration directory for Laniakea. It is used 3 | to generate a temporary environment to build and test Laniakea in, 4 | as well as to run style checks on the code. 5 | -------------------------------------------------------------------------------- /tests/ci/containers.conf: -------------------------------------------------------------------------------- 1 | [containers] 2 | userns="host" 3 | ipcns="host" 4 | utsns="host" 5 | cgroupns="host" 6 | cgroups="disabled" 7 | log_driver = "k8s-file" 8 | [engine] 9 | cgroup_manager = "cgroupfs" 10 | events_logger="file" 11 | runtime="crun" 12 | -------------------------------------------------------------------------------- /tests/ci/install-native-deps.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Install Laniakea native dependencies 4 | # 5 | set -e 6 | set -x 7 | 8 | export DEBIAN_FRONTEND=noninteractive 9 | 10 | # update caches 11 | apt-get update -qq 12 | 13 | # install build essentials 14 | apt-get install -yq \ 15 | eatmydata \ 16 | build-essential \ 17 | gdb 18 | 19 | # install dependencies for Laniakea 20 | eatmydata apt-get install -yq podman fuse-overlayfs 21 | eatmydata apt-get install -yq --no-install-recommends \ 22 | pkg-config \ 23 | meson \ 24 | systemd \ 25 | libsystemd-dev \ 26 | postgresql-client \ 27 | apt-utils \ 28 | libappstream-dev \ 29 | gir1.2-appstream-1.0 \ 30 | ostree \ 31 | flatpak \ 32 | flatpak-builder \ 33 | git \ 34 | debhelper \ 35 | dpkg-dev \ 36 | devscripts \ 37 | lintian \ 38 | bubblewrap \ 39 | npm 40 | 41 | eatmydata apt-get install -yq --no-install-recommends \ 42 | python3-pip \ 43 | python3-setuptools \ 44 | python3-virtualenv \ 45 | python3-pytest \ 46 | python3-gi \ 47 | python3-tomlkit \ 48 | python3-cairo-dev \ 49 | python3-sqlalchemy \ 50 | python3-alembic \ 51 | python3-psycopg2 \ 52 | python3-nacl \ 53 | python3-debian \ 54 | python3-apt \ 55 | python3-zmq \ 56 | python3-yaml \ 57 | python3-systemd \ 58 | python3-flask \ 59 | python3-flask-restful \ 60 | python3-flask-login \ 61 | python3-pytest-flask \ 62 | python3-humanize \ 63 | python3-marshmallow \ 64 | python3-pebble \ 65 | python3-requests \ 66 | python3-apscheduler \ 67 | python3-click \ 68 | python3-rich \ 69 | python3-voluptuous 70 | -------------------------------------------------------------------------------- /tests/ci/run-lint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # 5 | # This script is supposed to run inside the Laniakea Container 6 | # on the CI system. 7 | # 8 | 9 | cd build 10 | source venv/bin/activate 11 | set -x 12 | 13 | # 14 | # Linting 15 | # 16 | 17 | meson test -t10 -v --suite linters 18 | -------------------------------------------------------------------------------- /tests/ci/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # 5 | # This script is supposed to run inside the Laniakea Container 6 | # on the CI system. 7 | # 8 | 9 | cd build 10 | source venv/bin/activate 11 | set -x 12 | 13 | # 14 | # Build & Test 15 | # 16 | 17 | ninja 18 | 19 | # Test all the things! 20 | meson test -t10 --print-errorlogs -v 21 | 22 | # Test Installation 23 | ninja install 24 | -------------------------------------------------------------------------------- /tests/ci/run-venv-prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -x 4 | 5 | # 6 | # This script is supposed to run inside the Laniakea Container 7 | # on the CI system. 8 | # 9 | 10 | # 11 | # Prepare Virtualenv and install dependencies 12 | # 13 | 14 | mkdir build && cd build 15 | virtualenv --system-site-packages venv 16 | 17 | set +x 18 | source venv/bin/activate 19 | set -x 20 | 21 | pip install -r ../requirements.txt 22 | pip install -r ../requirements.tests.txt 23 | 24 | if [ "$1" = "lint-only" ]; then 25 | meson \ 26 | --prefix=/tmp/lk-install-root \ 27 | -Ddownload-npm=false \ 28 | -Dlinting=true \ 29 | .. 30 | else 31 | meson \ 32 | --prefix=/tmp/lk-install-root \ 33 | .. 34 | fi; 35 | -------------------------------------------------------------------------------- /tests/ci/storage.conf: -------------------------------------------------------------------------------- 1 | [storage] 2 | driver = "overlay" 3 | runroot = "/run/containers/storage" 4 | graphroot = "/var/lib/containers/storage" 5 | 6 | [storage.options] 7 | mount_program = "/usr/bin/fuse-overlayfs" 8 | -------------------------------------------------------------------------------- /tests/containers/postgres/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:bookworm 2 | 3 | # prepare 4 | ENV LANG C.UTF-8 5 | ENV DEBIAN_FRONTEND noninteractive 6 | RUN apt-get update -qq 7 | 8 | # set up Postgres with debversion extension for use in Laniakea testssuite 9 | RUN apt-get install --no-install-recommends -yq \ 10 | postgresql-15 \ 11 | postgresql-15-debversion 12 | 13 | RUN echo "/etc/init.d/postgresql start && exit 0" > /etc/rc.local 14 | RUN /etc/init.d/postgresql start && \ 15 | su postgres -c "psql -c \"CREATE USER lkdbuser_test WITH PASSWORD 'notReallySecret';\"" && \ 16 | su postgres -c "psql -c \"CREATE DATABASE laniakea_unittest WITH OWNER lkdbuser_test;\"" && \ 17 | su postgres -c "psql -c \"GRANT ALL PRIVILEGES ON DATABASE laniakea_unittest TO lkdbuser_test;\"" && \ 18 | su postgres -c "psql -c \"CREATE EXTENSION IF NOT EXISTS debversion;\" laniakea_unittest" 19 | 20 | USER postgres 21 | RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/15/main/pg_hba.conf 22 | 23 | RUN echo "listen_addresses = '*'" >> /etc/postgresql/15/main/postgresql.conf 24 | RUN echo "log_destination = 'stderr'" >> /etc/postgresql/15/main/postgresql.conf 25 | 26 | EXPOSE 5434 27 | CMD ["/usr/lib/postgresql/15/bin/postgres", "-D", "/var/lib/postgresql/15/main", "-c", "config_file=/etc/postgresql/15/main/postgresql.conf", "-p", "5432"] 28 | -------------------------------------------------------------------------------- /tests/meson.build: -------------------------------------------------------------------------------- 1 | # Meson definition for Laniakea System and Integration tests 2 | 3 | # 4 | # Code Linters 5 | # 6 | if get_option('linting') 7 | pylint_paths = [ 8 | join_paths(source_root, 'src'), 9 | join_paths(source_root, 'tests'), 10 | # join_paths(source_root, 'contrib') 11 | ] 12 | 13 | flake8_exe = find_program('flake8') 14 | test('flake8', 15 | flake8_exe, 16 | args: ['--show-source', 17 | '--statistics', 18 | source_root], 19 | workdir: source_root, 20 | suite: 'linters', 21 | timeout: 180, 22 | ) 23 | 24 | pylint_exe = find_program('pylint') 25 | test('pylint', 26 | py, 27 | args: [pylint_exe.full_path(), 28 | '-f', 'colorized', 29 | pylint_paths], 30 | workdir: source_root, 31 | suite: 'linters', 32 | timeout: 180, 33 | ) 34 | 35 | mypy_exe = find_program('mypy') 36 | mypy_typeinst_args = [] 37 | if get_option('mypy-install-types') 38 | mypy_typeinst_args = ['--install-types', '--non-interactive'] 39 | endif 40 | test('mypy', 41 | py, 42 | args: [mypy_exe.full_path(), 43 | mypy_typeinst_args, 44 | join_paths(source_root, 'src'), 45 | '--exclude', 'src/(webdash|webswview|webupload)/(manage|wsgi)\\.py$|src/laniakea/alembic/env\\.py$', 46 | ], 47 | workdir: source_root, 48 | suite: 'linters', 49 | timeout: 180, 50 | ) 51 | 52 | isort_exe = find_program('isort') 53 | test('isort', 54 | py, 55 | args: [isort_exe.full_path(), 56 | '--diff', '.'], 57 | workdir: source_root, 58 | suite: 'linters', 59 | timeout: 180, 60 | ) 61 | 62 | black_exe = find_program('black') 63 | test('black', 64 | py, 65 | args: [black_exe.full_path(), 66 | '--diff', '.'], 67 | workdir: source_root, 68 | suite: 'linters', 69 | timeout: 180, 70 | ) 71 | endif 72 | 73 | py_exe = find_program('python3') 74 | test('pytest', 75 | py_exe, 76 | args: ['-m', 'pytest', '-x'], 77 | workdir: source_root, 78 | is_parallel: false, 79 | suite: 'integration', 80 | timeout: 6720, # set to -1 once we can bump minimum Meson version to 0.58 81 | ) 82 | -------------------------------------------------------------------------------- /tests/plugins/pytest_podman/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 pytest-docker contributors 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. -------------------------------------------------------------------------------- /tests/plugins/pytest_podman/__init__.py: -------------------------------------------------------------------------------- 1 | from .plugin import ( 2 | podman_ip, 3 | podman_cleanup, 4 | podman_services, 5 | podman_compose_file, 6 | podman_class_services, 7 | podman_module_services, 8 | podman_package_services, 9 | podman_function_services, 10 | podman_compose_project_name, 11 | podman_compose_class_project_name, 12 | podman_compose_module_project_name, 13 | podman_compose_package_project_name, 14 | podman_compose_function_project_name, 15 | ) 16 | 17 | __all__ = [ 18 | 'podman_cleanup', 19 | 'podman_compose_file', 20 | 'podman_compose_project_name', 21 | 'podman_compose_package_project_name', 22 | 'podman_compose_module_project_name', 23 | 'podman_compose_class_project_name', 24 | 'podman_compose_function_project_name', 25 | 'podman_ip', 26 | 'podman_services', 27 | 'podman_package_services', 28 | 'podman_module_services', 29 | 'podman_class_services', 30 | 'podman_function_services', 31 | ] 32 | -------------------------------------------------------------------------------- /tests/podman-compose.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: '2' 3 | services: 4 | postgres: 5 | build: "./containers/postgres" 6 | ports: 7 | - "5432" 8 | -------------------------------------------------------------------------------- /tests/test_data/changes/1.changes: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/changes/1.changes -------------------------------------------------------------------------------- /tests/test_data/changes/bogus-post.changes: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNED MESSAGE----- 2 | Hash: SHA1 3 | 4 | Format: 1.7 5 | Date: Tue, 9 Sep 2003 01:16:01 +0100 6 | Source: gawk 7 | Binary: gawk 8 | Architecture: source i386 9 | Version: 1:3.1.3-2 10 | Distribution: unstable 11 | Urgency: low 12 | Maintainer: James Troup 13 | Changed-By: James Troup 14 | Description: 15 | gawk - GNU awk, a pattern scanning and processing language 16 | Closes: 204699 204701 17 | Changes: 18 | gawk (1:3.1.3-2) unstable; urgency=low 19 | . 20 | * debian/control (Standards-Version): bump to 3.6.1.0. 21 | . 22 | * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]]. 23 | Thanks to for reporting the bug and forwarding it 24 | upstream. Closes: #204701 25 | . 26 | * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix 27 | [\x80-\xff]. Thanks to for reporting the bug and 28 | forwarding it upstream. Closes: #204699 29 | Files: 30 | 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc 31 | 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz 32 | 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb 33 | 34 | -----BEGIN PGP SIGNATURE----- 35 | Version: GnuPG v1.0.6 (GNU/Linux) 36 | 37 | iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau 38 | fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB 39 | =O7Gh 40 | -----END PGP SIGNATURE----- 41 | You: have been 0wned 42 | -------------------------------------------------------------------------------- /tests/test_data/changes/bogus-pre.changes: -------------------------------------------------------------------------------- 1 | You: have been 0wned 2 | -----BEGIN PGP SIGNED MESSAGE----- 3 | Hash: SHA1 4 | 5 | Format: 1.7 6 | Date: Tue, 9 Sep 2003 01:16:01 +0100 7 | Source: gawk 8 | Binary: gawk 9 | Architecture: source i386 10 | Version: 1:3.1.3-2 11 | Distribution: unstable 12 | Urgency: low 13 | Maintainer: James Troup 14 | Changed-By: James Troup 15 | Description: 16 | gawk - GNU awk, a pattern scanning and processing language 17 | Closes: 204699 204701 18 | Changes: 19 | gawk (1:3.1.3-2) unstable; urgency=low 20 | . 21 | * debian/control (Standards-Version): bump to 3.6.1.0. 22 | . 23 | * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]]. 24 | Thanks to for reporting the bug and forwarding it 25 | upstream. Closes: #204701 26 | . 27 | * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix 28 | [\x80-\xff]. Thanks to for reporting the bug and 29 | forwarding it upstream. Closes: #204699 30 | Files: 31 | 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc 32 | 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz 33 | 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb 34 | 35 | -----BEGIN PGP SIGNATURE----- 36 | Version: GnuPG v1.0.6 (GNU/Linux) 37 | 38 | iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau 39 | fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB 40 | =O7Gh 41 | -----END PGP SIGNATURE----- 42 | -------------------------------------------------------------------------------- /tests/test_data/changes/valid.changes: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNED MESSAGE----- 2 | Hash: SHA1 3 | 4 | Format: 1.7 5 | Date: Tue, 9 Sep 2003 01:16:01 +0100 6 | Source: gawk 7 | Binary: gawk 8 | Architecture: source i386 9 | Version: 1:3.1.3-2 10 | Distribution: unstable 11 | Urgency: low 12 | Maintainer: James Troup 13 | Changed-By: James Troup 14 | Description: 15 | gawk - GNU awk, a pattern scanning and processing language 16 | Closes: 204699 204701 17 | Changes: 18 | gawk (1:3.1.3-2) unstable; urgency=low 19 | . 20 | * debian/control (Standards-Version): bump to 3.6.1.0. 21 | . 22 | * 02_fix-ascii.dpatch: new patch from upstream to fix [[:ascii:]]. 23 | Thanks to for reporting the bug and forwarding it 24 | upstream. Closes: #204701 25 | . 26 | * 03_fix-high-char-ranges.dpatch: new patch from upstream to fix 27 | [\x80-\xff]. Thanks to for reporting the bug and 28 | forwarding it upstream. Closes: #204699 29 | Files: 30 | 0e6542c48bcc9d9586fc8ebe4e7242a4 561 interpreters optional gawk_3.1.3-2.dsc 31 | 50a29dce4a2c6e2ac38069eb7c41d9c4 8302 interpreters optional gawk_3.1.3-2.diff.gz 32 | 5a255c7b421ac699804212e10205f22d 871114 interpreters optional gawk_3.1.3-2_i386.deb 33 | 34 | -----BEGIN PGP SIGNATURE----- 35 | Version: GnuPG v1.0.6 (GNU/Linux) 36 | 37 | iEYEARECAAYFAj9dHWsACgkQgD/uEicUG7DUnACglndvU4LCA0/k36Qp873N0Sau 38 | fCwAoMdgIOUBcUfMqXvVnxdW03ev5bNB 39 | =O7Gh 40 | -----END PGP SIGNATURE----- 41 | -------------------------------------------------------------------------------- /tests/test_data/config/archive-config.toml: -------------------------------------------------------------------------------- 1 | DistroTag = "utest" 2 | 3 | [[Repositories]] 4 | name = "master" 5 | origin = "ACME Inc." 6 | 7 | [[Repositories]] 8 | name = "master-debug" 9 | origin = "ACME Inc." 10 | is_debug = true 11 | debug_for = 'master' 12 | 13 | [[Repositories]] 14 | name = "extra" 15 | origin = "ACME Inc." 16 | 17 | [[Components]] 18 | name = "main" 19 | summary = "Supported Packages" 20 | 21 | [[Components]] 22 | name = "contrib" 23 | summary = "Free software with non-free or external dependencies" 24 | 25 | [[Components]] 26 | name = "non-free" 27 | summary = "Unsuported, Closed-Source Packages" 28 | 29 | [[Architectures]] 30 | name = "amd64" 31 | summary = "AMD x86-64 architecture" 32 | 33 | [[Architectures]] 34 | name = "arm64" 35 | summary = "64-Bit ARM" 36 | 37 | [[Suites]] 38 | name = "unstable" 39 | alias = "" 40 | summary = "Development Suite" 41 | version = "2.0" 42 | arch_names = ["amd64", "arm64"] 43 | component_names = ["main", "contrib", "non-free"] 44 | devel_target = true 45 | 46 | [[Suites]] 47 | name = "unstable-debug" 48 | alias = "" 49 | summary = "Development Suite (Debug Symbols)" 50 | version = "2.0" 51 | arch_names = ["amd64", "arm64"] 52 | component_names = ["main", "contrib", "non-free"] 53 | dbgsym_policy = "only-debug" 54 | debug_suite_for = "unstable" 55 | 56 | [[Suites]] 57 | name = "stable" 58 | alias = "" 59 | summary = "Stable 1.0 Release" 60 | version = "1.0" 61 | arch_names = ["amd64", "arm64"] 62 | component_names = ["main"] 63 | 64 | [[RepoSuiteSettings]] 65 | repo_name = "master" 66 | suite_name = "unstable" 67 | signingkeys = ["8BB746C63FF5346326C19ABDEFD8BD07D224478F"] 68 | announce_emails = [] 69 | accept_uploads = true 70 | 71 | [[RepoSuiteSettings]] 72 | repo_name = "master-debug" 73 | suite_name = "unstable-debug" 74 | signingkeys = ["8BB746C63FF5346326C19ABDEFD8BD07D224478F"] 75 | announce_emails = [] 76 | 77 | [[RepoSuiteSettings]] 78 | repo_name = "master" 79 | suite_name = "stable" 80 | signingkeys = ["8BB746C63FF5346326C19ABDEFD8BD07D224478F"] 81 | announce_emails = [] 82 | 83 | [[RepoSuiteSettings]] 84 | repo_name = "extra" 85 | suite_name = "unstable" 86 | signingkeys = ["8BB746C63FF5346326C19ABDEFD8BD07D224478F"] 87 | announce_emails = [] 88 | accept_uploads = true 89 | -------------------------------------------------------------------------------- /tests/test_data/config/base-config.toml: -------------------------------------------------------------------------------- 1 | # Laniakea Unittest Configuration 2 | 3 | Workspace = "/tmp/test-lkws/" 4 | 5 | UploadUrl = "https://laniakea.example.org/_upload" 6 | 7 | [Archive] 8 | path = "???" 9 | develSuite = "dasyatis" 10 | incomingSuite = "staging" 11 | distroTag = "test" 12 | 13 | [Database] 14 | db = "laniakea_unittest" 15 | user = "lkdbuser_test" 16 | password = "notReallySecret" 17 | # our CI server Postgres DB may be quite slow 18 | slow_connection = true 19 | 20 | [Synchrotron] 21 | SourceKeyringDir = "/etc/apt/trusted.gpg.d/" 22 | 23 | [Lighthouse.endpoints] 24 | jobs = [ "tcp://*:5570",] 25 | submit = [ "tcp://*:5571",] 26 | publish = [ "tcp://*:5572",] 27 | 28 | [Lighthouse.servers] 29 | jobs = [ "tcp://localhost:5570",] 30 | submit = [ "tcp://localhost:5571",] 31 | publish = [ "tcp://localhost:5572",] 32 | -------------------------------------------------------------------------------- /tests/test_data/dep11/CID-Index-amd64.json.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/dep11/CID-Index-amd64.json.xz -------------------------------------------------------------------------------- /tests/test_data/dep11/Components-amd64.yml.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/dep11/Components-amd64.yml.xz -------------------------------------------------------------------------------- /tests/test_data/dep11/fetch-appstream.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [ "${LK_REPO_NAME}" != "master" ]; then 5 | # we will only have data for the "master" repository 6 | exit 0 7 | fi 8 | 9 | SCRIPT_PATH=$(readlink -f "$0") 10 | BASEDIR=$(dirname "$SCRIPT_PATH") 11 | 12 | # A production script would maybe download from a network location here, 13 | # but we just copy our sample data to the destination. 14 | mkdir -p ${LK_DATA_TARGET_DIR}/unstable/main 15 | cp ${BASEDIR}/*.xz ${BASEDIR}/*.tar.gz ${LK_DATA_TARGET_DIR}/unstable/main/ 16 | -------------------------------------------------------------------------------- /tests/test_data/dep11/icons-64x64.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/dep11/icons-64x64.tar.gz -------------------------------------------------------------------------------- /tests/test_data/gpg/BrokenSigFile.txt: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNED MESSAGE----- 2 | Hash: SHA1 3 | 4 | I am a harmless test file for the Laniakea Project that 5 | has been signed for the testsuite to validate its signature. 6 | -----BEGIN PGP SIGNATURE----- 7 | Version: GnuPG v1 8 | 9 | iQIcBAEBAgAGBQJX1aGVAAoJEO/YvQfSJEeP6OMQAN7tf34zCKlIC83xnG1vHCLZ 10 | sIKvEyzhlOXl8sJ4oULNGq/P06qxscck4c09EemGszIhBBkNSrT25d/gaDc9boPS 11 | idNXaEDEJdoIWEnytiUgJjMulYwFHd97G39L947Yy/vnKgrCT9xxqntuQFLsuLdo 12 | Z0HhZJ2PIHT2lSlAFOMvTydNGJtIWsbDZKbLOOLoMvX32Aijgd5mmt3gXlcimgot 13 | ec9slrOylh0GxKujDZkl5tsFgwlKP8wqy8m43wImakJQ+6nJ/Y0nAYQuQRuZ64wD 14 | x8DpPpapn7ArlqyZ+NLaC3eX0bAD4mF3XNhdPRyI2jmKo+cTQCc3txNxMxXWtthn 15 | MbvkZWdJmXOa4Ja3ndEDXwF6sMbqU6HCBtGZX77T5rcXuFvGSGEcMJLF40K8pPGh 16 | K3rbC4prmc7cXSchX8FK3wMu1XYFrdAcXN5f+chLkN+obiGUSbr4Y+heS1UWScgH 17 | QaLNfoMry+ZDExUMdYsaxtzbUVdfqbsERx3I6jxXAvmj/LOwamxcSkRyl9sTOe2w 18 | XlyV/oW/uClB+8WxxVNXKKilvb36og/bvz7J/kyf8vCrBgZzYPgknFiqfLEvUOB/ 19 | r+z709Vjtm6fKR09TQ08PiO6+16TDb9cTlh0LVXQgXcNOecoRwAeiQneSjkvN722 20 | vGnAdzwPt9zrWMvv+6iW 21 | =D/O+ 22 | -----END PGP SIGNATURE----- 23 | -------------------------------------------------------------------------------- /tests/test_data/gpg/NotSignedFile.txt: -------------------------------------------------------------------------------- 1 | I am a not-signed file. 2 | -------------------------------------------------------------------------------- /tests/test_data/gpg/SignedFile.txt: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP SIGNED MESSAGE----- 2 | Hash: SHA1 3 | 4 | I am a harmless test file for the Laniakea Project that 5 | has been signed for the testsuite to validate its signature. 6 | -----BEGIN PGP SIGNATURE----- 7 | Version: GnuPG v1 8 | 9 | iQIcBAEBAgAGBQJX1aGVAAoJEO/YvQfSJEeP6OMQAN7tf34zCKlIC83xnG1vHCLZ 10 | sIKvEyzhlOXl8sJ4oULNGq/P06qxscck4c09EemGszIhBBkNSrT25d/gaDc9boPS 11 | idNXaEDEJdoIWEnytiUgJjMulYwFHd97G39L947Yy/vnKgrCT9xxqntuQFLsuLdo 12 | Z0HhZJ2PIHT2lSlAFOMvTydNGJtIWsbDZKbLOOLoMvX32Aijgd5mmt3gXlcimgot 13 | ec9slrOylh0GxKujDZkl5tsFgwlKP8wqy8m43wImakJQ+6nJ/Y0nAYQuQRuZ64wD 14 | x8DpPpapn7ArlqyZ+NLaC3eX0bFD4mF3XNhdPRyI2jmKo+cTQCc3txNxMxXWtthn 15 | MbvkZWdJmXOa4Ja3ndEDXwF6sMbqU6HCBtGZX77T5rcXuFvGSGEcMJLF40K8pPGh 16 | K3rbC4prmc7cXSchX8FK3wMu1XYFrdAcXN5f+chLkN+obiGUSbr4Y+heS1UWScgH 17 | QaLNfoMry+ZDExUMdYsaxtzbUVdfqbsERx3I6jxXAvmj/LOwamxcSkRyl9sTOe2w 18 | XlyV/oW/uClB+8WxxVNXKKilvb36og/bvz7J/kyf8vCrBgZzYPgknFiqfLEvUOB/ 19 | r+z709Vjtm6fKR09TQ08PiO6+16TDb9cTlh0LVXQgXcNOecoRwAeiQneSjkvN722 20 | vGnAdzwPt9zrWMvv+6iW 21 | =D/O+ 22 | -----END PGP SIGNATURE----- 23 | -------------------------------------------------------------------------------- /tests/test_data/gpg/keyrings/keyring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/gpg/keyrings/keyring.gpg -------------------------------------------------------------------------------- /tests/test_data/gpg/keyrings/other-keyring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/gpg/keyrings/other-keyring.gpg -------------------------------------------------------------------------------- /tests/test_data/gpg/secret-home/.gpg-v21-migrated: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/gpg/secret-home/.gpg-v21-migrated -------------------------------------------------------------------------------- /tests/test_data/gpg/secret-home/private-keys-v1.d/37E2C55C7C93586DA424642111539C2F4952141D.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/gpg/secret-home/private-keys-v1.d/37E2C55C7C93586DA424642111539C2F4952141D.key -------------------------------------------------------------------------------- /tests/test_data/gpg/secret-home/pubring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/gpg/secret-home/pubring.gpg -------------------------------------------------------------------------------- /tests/test_data/gpg/secret-home/secring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/gpg/secret-home/secring.gpg -------------------------------------------------------------------------------- /tests/test_data/gpg/secret-home/trustdb.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/gpg/secret-home/trustdb.gpg -------------------------------------------------------------------------------- /tests/test_data/packages/.gitignore: -------------------------------------------------------------------------------- 1 | /*.changes 2 | /*.deb 3 | /*.diff.gz 4 | /*.dsc 5 | /*.tar.gz 6 | /stamp-* 7 | 8 | /*/debian/files 9 | -------------------------------------------------------------------------------- /tests/test_data/packages/create_keys: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | export GNUPGHOME=$PWD/gpg 4 | 5 | create_key() { 6 | KEYUID="$1" 7 | EPOCH="$2" 8 | echo creating key for "$KEYUID" 9 | EPOCH_OPT="" 10 | if [ "$EPOCH" != "" ] 11 | then 12 | EPOCH_OPT=" --faked-system-time $EPOCH " 13 | fi 14 | gpg $EPOCH_OPT --batch --passphrase "" --quick-generate-key "$KEYUID" default default never 15 | 16 | 17 | } 18 | 19 | # create keys with date in the past, to be able to manually expire them at some 20 | # later time in the past for testing 21 | create_key "Développeur " 20200202T200000 22 | create_key "Snowman ☃ " 20200202T200000 23 | -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/.gpg-v21-migrated: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/.gpg-v21-migrated -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/gpg.conf: -------------------------------------------------------------------------------- 1 | personal-digest-preferences SHA256 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/openpgp-revocs.d/22865D3DA7CF3DE67C1AF9A74014AB2D03010AA9.rev: -------------------------------------------------------------------------------- 1 | This is a revocation certificate for the OpenPGP key: 2 | 3 | pub rsa3072 2020-02-02 [SC] 4 | 22865D3DA7CF3DE67C1AF9A74014AB2D03010AA9 5 | uid Développeur 6 | 7 | A revocation certificate is a kind of "kill switch" to publicly 8 | declare that a key shall not anymore be used. It is not possible 9 | to retract such a revocation certificate once it has been published. 10 | 11 | Use it to revoke this key in case of a compromise or loss of 12 | the secret key. However, if the secret key is still accessible, 13 | it is better to generate a new revocation certificate and give 14 | a reason for the revocation. For details see the description of 15 | of the gpg command "--generate-revocation" in the GnuPG manual. 16 | 17 | To avoid an accidental use of this file, a colon has been inserted 18 | before the 5 dashes below. Remove this colon with a text editor 19 | before importing and publishing this revocation certificate. 20 | 21 | :-----BEGIN PGP PUBLIC KEY BLOCK----- 22 | Comment: This is a revocation certificate 23 | 24 | iQG2BCABCgAgFiEEIoZdPafPPeZ8GvmnQBSrLQMBCqkFAl43KkICHQAACgkQQBSr 25 | LQMBCqkMWgv/SS3yMN3JDX9myGlU9JHwANNpoNIvvtcIM0eZSXGh/WBcOtnZUg69 26 | b9xM8lYHkW66hH+/lUuUeOMRKB5X+VbBQVQKBDluOHypyQF1Hev8TKTuQX29bXfx 27 | 8q2xxiyf4L8SpQN/Xg8tR9rtO+hwcZ/7mRlxwrh6x1ZQTHd13YL0VNGqGSeuMEjV 28 | sAHD3z6LCffuVcC2pXlNa4jVUbAToXQiL1fXO7VvmB/gyZD+1o2MZUskZWvdYz/1 29 | OPoIl3U6bYK60hA0vowWh1PcGGaiYFn0b/T2kjT/x8/cA98472PtTvrydifaSYZc 30 | XxWyrnI70qO7+noM0DlFV/ykrXKkuz0XKZmCVQfBD+tlxE24qmAh50yA9+IDagCP 31 | 1LhSdQa2D7dQh0F8+FphouwgHJZgrTdJHt3M1dkUc7q5ilUwH1E2XtcXnDTsm+oM 32 | i5DVIyYDqNAR+hUCGQss/pRngbu/j6cKP3bhx78tt7nkmNsnoUZ2CFuGwgP9u2nb 33 | 2ewd+j8XmhHN 34 | =uyRH 35 | -----END PGP PUBLIC KEY BLOCK----- 36 | -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/openpgp-revocs.d/589E8FA542378066E944B6222F7C63E8F3A2C549.rev: -------------------------------------------------------------------------------- 1 | This is a revocation certificate for the OpenPGP key: 2 | 3 | pub rsa3072 2020-02-02 [SC] 4 | 589E8FA542378066E944B6222F7C63E8F3A2C549 5 | uid Snowman ☃ 6 | 7 | A revocation certificate is a kind of "kill switch" to publicly 8 | declare that a key shall not anymore be used. It is not possible 9 | to retract such a revocation certificate once it has been published. 10 | 11 | Use it to revoke this key in case of a compromise or loss of 12 | the secret key. However, if the secret key is still accessible, 13 | it is better to generate a new revocation certificate and give 14 | a reason for the revocation. For details see the description of 15 | of the gpg command "--generate-revocation" in the GnuPG manual. 16 | 17 | To avoid an accidental use of this file, a colon has been inserted 18 | before the 5 dashes below. Remove this colon with a text editor 19 | before importing and publishing this revocation certificate. 20 | 21 | :-----BEGIN PGP PUBLIC KEY BLOCK----- 22 | Comment: This is a revocation certificate 23 | 24 | iQG2BCABCgAgFiEEWJ6PpUI3gGbpRLYiL3xj6POixUkFAl43KkECHQAACgkQL3xj 25 | 6POixUldGQv5AZv6hSt21Yu3rQQ5PlvHZ1JGcsRbJgxYfNkGdt6+pxij/Em6eaCH 26 | x0NIVEiPrOZ9ub77b1tiMfXJNnZtGxtIqgaKZwnmHNEYMAd+1kvds3FKWM9SzQl0 27 | hMFq+f+BOiGc7xGDld0szQbFIjM4clnZsv0TsJnGnHpq5I2F/L3D93p6Jml3iR+H 28 | pMv4nXM7sRD701GrUwEcZ74Boba4EUy8LZiyyX1vzmsuAUcPoxfKOCrRqz7KRvNt 29 | 0jxcRp6Gj/rQb5d5sDihVtIIpg/f1e/bt3jVpNqMrxc777WDTFROdzS0An75Wl3Z 30 | zXu09KopFFZ58lUlU/FWwx0w3iJJK/TvmsuST1pQ7h9dfe26f1kOIXp22trqT6qg 31 | MHAQ6ljPnia/VyM19akP6rbQGr5kxeVjf7fq+CD85XZ50Pm5m/yWZOPyXsC4388y 32 | YGu1oZKcBxv59gzr8nApR9SsePPfmFl7zyyDuTmwN0Ctbkhq3IT3AStdMdXBCX7e 33 | OBzEPgn6iZQP 34 | =fLQU 35 | -----END PGP PUBLIC KEY BLOCK----- 36 | -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/private-keys-v1.d/0455C3AF7F36C15A0C6A7B0638D52E313663C0BD.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/private-keys-v1.d/0455C3AF7F36C15A0C6A7B0638D52E313663C0BD.key -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/private-keys-v1.d/472886E308A3F53B1BB34917FAE6B0D696ED9A0A.key: -------------------------------------------------------------------------------- 1 | Key: (private-key (rsa (n #00A98B0E43A63A4657795340D23CA8D41DB6966AB99C 2 | C6774CA492B5265CB3E61A4D3698E923B0D9EDF716396A499AF8CC2AF9B1AC83221151 3 | E6AA0FD58C871B9B1E024D25B3EAFD3869B15A48AD44D86E93DEE3CA938EA83DA27B63 4 | D12CA6B78B6F6308B6043A10651E1AED31443A3F09ACDD7200EF0D9B7AA1868D58E049 5 | 95D3#)(e #010001#)(d #49436DC68DEE60B72C166DCC6BAA08FF4E0771D703883FC5 6 | 3ED8A6AF0D20302EED6ECA64F4A757851D60DD2EB0DFE6E3532ED33858F23FC9C48378 7 | 942F45B3078097716CD801FEE51D3CEE413528ABCB7B6EDB6E58FDE0D38F4710166188 8 | 6B2C4ABF3A504CC5A3525C1E67EB0E513AF25B205C987F4BBAA3A20825D314B45801#) 9 | (p #00C78989FBC6246895F4B4EA43801FF50EA85962410E7A7C547215E12AD56A250C 10 | 5AE72F57704C0B7EC44EC1569773E90CCED1F1049992C517C13A63046E323EE1#)(q 11 | #00D984BFA762813D364E7ECADDCE2CFA9F7E3AF544C77FD58D58A72DEB06D4E67C47 12 | 4A56C533FC0C342B13013F23683DA833C9A04A790573518CE1EF12D4F3EF33#)(u 13 | #6C181A694145B1DDE5AFEBF7501BC86A8AFC4F9F79464A2384E75019C83130C2D068 14 | A9EC217AE461DE2E50193F84AE4E6D3E593741505AB398B676957C3407F8#))) 15 | -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/private-keys-v1.d/8CB0C561CAB10EEF594CBB5835161A5E5A76A1DA.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/private-keys-v1.d/8CB0C561CAB10EEF594CBB5835161A5E5A76A1DA.key -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/private-keys-v1.d/A0405CB8F782F995AB5912C7D42AB38FE9EA7F50.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/private-keys-v1.d/A0405CB8F782F995AB5912C7D42AB38FE9EA7F50.key -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/private-keys-v1.d/AD0058FBD72B80D255ACB344431BF5A7D5B204C6.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/private-keys-v1.d/AD0058FBD72B80D255ACB344431BF5A7D5B204C6.key -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/private-keys-v1.d/EB9EC8B0681FEAA9FA56AEF4B68DD0D15DE0384F.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/private-keys-v1.d/EB9EC8B0681FEAA9FA56AEF4B68DD0D15DE0384F.key -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/pubkey_amaintainer.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/pubkey_amaintainer.gpg -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/pubkey_developpeur.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/pubkey_developpeur.gpg -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/pubkey_snowman.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/pubkey_snowman.gpg -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/pubring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/pubring.gpg -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/random_seed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/random_seed -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/secring.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/secring.gpg -------------------------------------------------------------------------------- /tests/test_data/packages/gpg/trustdb.gpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/packages/gpg/trustdb.gpg -------------------------------------------------------------------------------- /tests/test_data/packages/grave-0.1/debian/README.source: -------------------------------------------------------------------------------- 1 | This is è package. 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/grave-0.1/debian/changelog: -------------------------------------------------------------------------------- 1 | grave (0.1-1) unstable; urgency=low 2 | 3 | * Initial release. "è" 4 | 5 | -- Développeur Fri, 08 Jun 2012 18:10:01 +0200 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/grave-0.1/debian/control: -------------------------------------------------------------------------------- 1 | Source: grave 2 | Section: misc 3 | Priority: optional 4 | Maintainer: Développeur 5 | Build-Depends: debhelper-compat (= 12) 6 | Rules-Requires-Root: no 7 | 8 | Package: grave 9 | Architecture: all 10 | Depends: ${misc:Depends} 11 | Description: è package 12 | è package 13 | -------------------------------------------------------------------------------- /tests/test_data/packages/grave-0.1/debian/copyright: -------------------------------------------------------------------------------- 1 | This is a package by Développeur 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/grave-0.1/debian/grave.install: -------------------------------------------------------------------------------- 1 | some-file usr/share/grave-è 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/grave-0.1/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | %: 3 | dh $@ 4 | -------------------------------------------------------------------------------- /tests/test_data/packages/grave-0.1/some-file: -------------------------------------------------------------------------------- 1 | some-text è 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/linux-42.0/debian/changelog: -------------------------------------------------------------------------------- 1 | linux (42.0-1) unstable; urgency=medium 2 | 3 | * Initial release. 4 | 5 | -- A Maintainer Wed, 09 Aug 2017 19:52:37 +0200 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/linux-42.0/debian/control: -------------------------------------------------------------------------------- 1 | Source: linux 2 | Section: kernel 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Build-Depends: debhelper-compat (= 12) 6 | Rules-Requires-Root: no 7 | 8 | Package: linux-image-all 9 | Architecture: all 10 | Depends: ${misc:Depends} 11 | Description: GNU Emacs editor (kernel) 12 | GNU Emacs is the extensible self-documenting text editor. 13 | This package contains the kernel component, formerly known as Linux. 14 | 15 | Package: linux-image-all-signed-template 16 | Architecture: all 17 | Depends: ${misc:Depends} 18 | Description: GNU Emacs editor (kernel, template for signed packages) 19 | GNU Emacs is the extensible self-documenting text editor. 20 | This package contains templates for building a signed version of the 21 | kernel component. 22 | -------------------------------------------------------------------------------- /tests/test_data/packages/linux-42.0/debian/linux-image-all-signed-template.install: -------------------------------------------------------------------------------- 1 | template usr/lib/linux-image-all-signed-template 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/linux-42.0/debian/linux-image-all.install: -------------------------------------------------------------------------------- 1 | modules/* lib/modules/linux-all 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/linux-42.0/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | 3 | %: 4 | dh $@ 5 | -------------------------------------------------------------------------------- /tests/test_data/packages/linux-42.0/debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/linux-42.0/modules/example.ko: -------------------------------------------------------------------------------- 1 | (define-emacs-module 2 | '((description . "I am an example emacs-kernel module") 3 | (author . "Ansgar Burchardt Fri, 08 Jun 2012 18:10:01 +0200 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/nonfree-package-0.1/debian/control: -------------------------------------------------------------------------------- 1 | Source: nonfree-package 2 | Section: non-free/misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Build-Depends: debhelper-compat (= 12) 6 | Rules-Requires-Root: no 7 | 8 | Package: nonfree-package 9 | Architecture: all 10 | Depends: ${misc:Depends} 11 | Description: a package 12 | a package 13 | -------------------------------------------------------------------------------- /tests/test_data/packages/nonfree-package-0.1/debian/nonfree-package.install: -------------------------------------------------------------------------------- 1 | some-file usr/share/nonfree-package 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/nonfree-package-0.1/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | %: 3 | dh $@ 4 | -------------------------------------------------------------------------------- /tests/test_data/packages/nonfree-package-0.1/some-file: -------------------------------------------------------------------------------- 1 | some-text 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/binnmu-0.1+b1/debian/changelog: -------------------------------------------------------------------------------- 1 | binnmupkg (0.1-1+b1) testing-proposed-updates; urgency=medium, binary-only=yes 2 | 3 | * Binary-only non-maintainer upload for amd64; no source changes. 4 | 5 | -- A Maintainer Sat, 13 Jul 2019 16:29:19 +0000 6 | 7 | binnmupkg (0.1-1) unstable; urgency=low 8 | 9 | * Initial release. 10 | 11 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 12 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/binnmu-0.1/debian/changelog: -------------------------------------------------------------------------------- 1 | binnmupkg (0.1-1) unstable; urgency=low 2 | 3 | * Initial release. 4 | 5 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/binnmu-0.2/debian/changelog: -------------------------------------------------------------------------------- 1 | binnmupkg (0.1-2) unstable; urgency=medium 2 | 3 | * Some changes 4 | 5 | -- Développeur Sat, 13 Jul 2019 10:29:19 +0000 6 | 7 | binnmupkg (0.1-1) unstable; urgency=low 8 | 9 | * Initial release. 10 | 11 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 12 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/binnmu/debian/binnmupkg.install: -------------------------------------------------------------------------------- 1 | some-file usr/share/apackage 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/binnmu/debian/control: -------------------------------------------------------------------------------- 1 | Source: binnmupkg 2 | Section: misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Uploaders: An Uploader 6 | Build-Depends: debhelper-compat (= 12) 7 | Rules-Requires-Root: no 8 | 9 | Package: binnmupkg 10 | Architecture: any 11 | Depends: ${misc:Depends} 12 | Description: a package 13 | a package 14 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/binnmu/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | %: 3 | dh $@ 4 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/binnmu/some-file: -------------------------------------------------------------------------------- 1 | some-text 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug-0.1/debian/changelog: -------------------------------------------------------------------------------- 1 | main-contrib-with-debug (0.1-1) unstable; urgency=low 2 | 3 | * Initial release. 4 | 5 | -- A Maintainer Tue, 16 Apr 2019 18:22:12 +0000 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug-0.2/debian/changelog: -------------------------------------------------------------------------------- 1 | main-contrib-with-debug (0.2-1) unstable; urgency=medium 2 | 3 | * new version 4 | 5 | -- Snowman ☃ Wed, 17 Apr 2019 12:33:48 +0000 6 | 7 | main-contrib-with-debug (0.1-1) unstable; urgency=low 8 | 9 | * Initial release. 10 | 11 | -- A Maintainer Tue, 16 Apr 2019 18:22:12 +0000 12 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug/Makefile: -------------------------------------------------------------------------------- 1 | 2 | default: test 3 | 4 | clean: 5 | rm -f test 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug/debian/contrib-with-debug.install: -------------------------------------------------------------------------------- 1 | test usr/bin 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug/debian/control: -------------------------------------------------------------------------------- 1 | Source: main-contrib-with-debug 2 | Section: misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Build-Depends: debhelper-compat (= 12) 6 | Rules-Requires-Root: no 7 | 8 | Package: main-package 9 | Architecture: all 10 | Depends: ${misc:Depends} 11 | Description: a package 12 | a package 13 | 14 | Package: contrib-with-debug 15 | Architecture: any 16 | Section: contrib/misc 17 | Depends: ${misc:Depends} 18 | Description: a package 19 | a package 20 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug/debian/main-package.install: -------------------------------------------------------------------------------- 1 | some-file usr/share/main-package 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | %: 3 | dh $@ 4 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug/some-file: -------------------------------------------------------------------------------- 1 | some text 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/main-contrib-with-debug/test.c: -------------------------------------------------------------------------------- 1 | 2 | 3 | int main(void) { 4 | return(0); 5 | } 6 | 7 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/package-0.1/debian/changelog: -------------------------------------------------------------------------------- 1 | package (0.1-1) unstable; urgency=low 2 | 3 | * Initial release. 4 | 5 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/package-0.2/debian/changelog: -------------------------------------------------------------------------------- 1 | package (0.2-1) unstable; urgency=medium 2 | 3 | * Change something 4 | 5 | -- Snowman ☃ Sat, 13 Apr 2019 06:50:19 +0000 6 | 7 | package (0.1-1) unstable; urgency=low 8 | 9 | * Initial release. 10 | 11 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 12 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/package/debian/control: -------------------------------------------------------------------------------- 1 | Source: package 2 | Section: misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Uploaders: An Uploader 6 | Build-Depends: debhelper-compat (= 12) 7 | Rules-Requires-Root: no 8 | 9 | Package: package 10 | Architecture: all 11 | Depends: ${misc:Depends} 12 | Description: a package 13 | a package 14 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/package/debian/package.install: -------------------------------------------------------------------------------- 1 | some-file usr/share/apackage 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/package/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | %: 3 | dh $@ 4 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/package/some-file: -------------------------------------------------------------------------------- 1 | some-text 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew-0.1/debian/changelog: -------------------------------------------------------------------------------- 1 | pkgnew (0.1-1) unstable; urgency=low 2 | 3 | * Initial release. 4 | 5 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew-0.1/debian/control: -------------------------------------------------------------------------------- 1 | Source: pkgnew 2 | Section: misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Uploaders: An Uploader 6 | Build-Depends: debhelper-compat (= 12) 7 | Rules-Requires-Root: no 8 | 9 | Package: pkg-all1 10 | Architecture: all 11 | Depends: ${misc:Depends} 12 | Description: a package 13 | a package 14 | 15 | Package: pkg-all2 16 | Architecture: all 17 | Depends: ${misc:Depends} 18 | Description: a package 19 | a package 20 | 21 | Package: pkg-any1 22 | Architecture: any 23 | Depends: ${misc:Depends} 24 | Description: a package 25 | a package 26 | 27 | Package: pkg-any2 28 | Architecture: any 29 | Depends: ${misc:Depends} 30 | Description: a package 31 | a package 32 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew-0.2/debian/changelog: -------------------------------------------------------------------------------- 1 | pkgnew (0.1-2) unstable; urgency=medium 2 | 3 | * Upload to unstable 4 | 5 | -- Snowman ☃ Thu, 08 Aug 2019 12:29:30 +0000 6 | 7 | pkgnew (0.1-2~exp) experimental; urgency=medium 8 | 9 | * Add binaries 10 | * Upload to experimental to go through new 11 | 12 | -- Snowman ☃ Thu, 08 Aug 2019 12:28:21 +0000 13 | 14 | pkgnew (0.1-1) unstable; urgency=low 15 | 16 | * Initial release. 17 | 18 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 19 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew-0.2/debian/control: -------------------------------------------------------------------------------- 1 | Source: pkgnew 2 | Section: misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Uploaders: An Uploader 6 | Build-Depends: debhelper-compat (= 12) 7 | Rules-Requires-Root: no 8 | 9 | Package: pkg-all1 10 | Architecture: all 11 | Depends: ${misc:Depends} 12 | Description: a package 13 | a package 14 | 15 | Package: pkg-all2 16 | Architecture: all 17 | Depends: ${misc:Depends} 18 | Description: a package 19 | a package 20 | 21 | Package: pkg-all3 22 | Architecture: all 23 | Depends: ${misc:Depends} 24 | Description: a package 25 | a package 26 | 27 | Package: pkg-all4 28 | Architecture: all 29 | Depends: ${misc:Depends} 30 | Description: a package 31 | a package 32 | 33 | Package: pkg-any1 34 | Architecture: any 35 | Depends: ${misc:Depends} 36 | Description: a package 37 | a package 38 | 39 | Package: pkg-any2 40 | Architecture: any 41 | Depends: ${misc:Depends} 42 | Description: a package 43 | a package 44 | 45 | Package: pkg-any3 46 | Architecture: any 47 | Depends: ${misc:Depends} 48 | Description: a package 49 | a package 50 | 51 | Package: pkg-any4 52 | Architecture: any 53 | Depends: ${misc:Depends} 54 | Description: a package 55 | a package 56 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew-0.2~exp/debian/changelog: -------------------------------------------------------------------------------- 1 | pkgnew (0.1-2~exp) experimental; urgency=medium 2 | 3 | * Add binaries 4 | * Upload to experimental to go through new 5 | 6 | -- Snowman ☃ Thu, 08 Aug 2019 12:28:21 +0000 7 | 8 | pkgnew (0.1-1) unstable; urgency=low 9 | 10 | * Initial release. 11 | 12 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 13 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew-0.2~exp/debian/control: -------------------------------------------------------------------------------- 1 | Source: pkgnew 2 | Section: misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Uploaders: An Uploader 6 | Build-Depends: debhelper-compat (= 12) 7 | Rules-Requires-Root: no 8 | 9 | Package: pkg-all1 10 | Architecture: all 11 | Depends: ${misc:Depends} 12 | Description: a package 13 | a package 14 | 15 | Package: pkg-all2 16 | Architecture: all 17 | Depends: ${misc:Depends} 18 | Description: a package 19 | a package 20 | 21 | Package: pkg-all3 22 | Architecture: all 23 | Depends: ${misc:Depends} 24 | Description: a package 25 | a package 26 | 27 | Package: pkg-all4 28 | Architecture: all 29 | Depends: ${misc:Depends} 30 | Description: a package 31 | a package 32 | 33 | Package: pkg-any1 34 | Architecture: any 35 | Depends: ${misc:Depends} 36 | Description: a package 37 | a package 38 | 39 | Package: pkg-any2 40 | Architecture: any 41 | Depends: ${misc:Depends} 42 | Description: a package 43 | a package 44 | 45 | Package: pkg-any3 46 | Architecture: any 47 | Depends: ${misc:Depends} 48 | Description: a package 49 | a package 50 | 51 | Package: pkg-any4 52 | Architecture: any 53 | Depends: ${misc:Depends} 54 | Description: a package 55 | a package 56 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew-0.3/debian/changelog: -------------------------------------------------------------------------------- 1 | pkgnew (0.1-3) unstable; urgency=medium 2 | 3 | * Another upload 4 | 5 | -- Snowman ☃ Thu, 08 Aug 2019 12:39:30 +0000 6 | 7 | pkgnew (0.1-2) unstable; urgency=medium 8 | 9 | * Upload to unstable 10 | 11 | -- Snowman ☃ Thu, 08 Aug 2019 12:29:30 +0000 12 | 13 | pkgnew (0.1-2~exp) experimental; urgency=medium 14 | 15 | * Add binaries 16 | * Upload to experimental to go through new 17 | 18 | -- Snowman ☃ Thu, 08 Aug 2019 12:28:21 +0000 19 | 20 | pkgnew (0.1-1) unstable; urgency=low 21 | 22 | * Initial release. 23 | 24 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 25 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew-0.3/debian/control: -------------------------------------------------------------------------------- 1 | Source: pkgnew 2 | Section: misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Uploaders: An Uploader 6 | Build-Depends: debhelper-compat (= 12) 7 | Rules-Requires-Root: no 8 | 9 | Package: pkg-all1 10 | Architecture: all 11 | Depends: ${misc:Depends} 12 | Description: a package 13 | a package 14 | 15 | Package: pkg-all2 16 | Architecture: all 17 | Depends: ${misc:Depends} 18 | Description: a package 19 | a package 20 | 21 | Package: pkg-all3 22 | Architecture: all 23 | Depends: ${misc:Depends} 24 | Description: a package 25 | a package 26 | 27 | Package: pkg-any1 28 | Architecture: any 29 | Depends: ${misc:Depends} 30 | Description: a package 31 | a package 32 | 33 | Package: pkg-any2 34 | Architecture: any 35 | Depends: ${misc:Depends} 36 | Description: a package 37 | a package 38 | 39 | Package: pkg-any3 40 | Architecture: any 41 | Depends: ${misc:Depends} 42 | Description: a package 43 | a package 44 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | %: 3 | dh $@ 4 | -------------------------------------------------------------------------------- /tests/test_data/packages/overlays/pkgnew/some-file: -------------------------------------------------------------------------------- 1 | some-text 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/package-built-using-0.1/debian/changelog: -------------------------------------------------------------------------------- 1 | package-built-using (0.1-1) unstable; urgency=low 2 | 3 | * Initial release. 4 | 5 | -- A Maintainer Fri, 08 Jun 2012 18:10:01 +0200 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/package-built-using-0.1/debian/control: -------------------------------------------------------------------------------- 1 | Source: package-built-using 2 | Section: misc 3 | Priority: optional 4 | Maintainer: A Maintainer 5 | Build-Depends: debhelper-compat (= 12) 6 | Rules-Requires-Root: no 7 | 8 | Package: package-built-using 9 | Architecture: all 10 | Depends: ${misc:Depends} 11 | Built-Using: package (= 0.1-1) 12 | Description: a package 13 | a package 14 | -------------------------------------------------------------------------------- /tests/test_data/packages/package-built-using-0.1/debian/package-built-using.install: -------------------------------------------------------------------------------- 1 | some-file usr/share/apackage 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/package-built-using-0.1/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | %: 3 | dh $@ 4 | -------------------------------------------------------------------------------- /tests/test_data/packages/package-built-using-0.1/some-file: -------------------------------------------------------------------------------- 1 | some-text 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/snowman-0.1/debian/README.source: -------------------------------------------------------------------------------- 1 | This is a ☃ package. 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/snowman-0.1/debian/changelog: -------------------------------------------------------------------------------- 1 | snowman (0.1-1) unstable; urgency=low 2 | 3 | * Initial release. ☃ 4 | 5 | -- Snowman ☃ Fri, 08 Jun 2012 18:10:01 +0200 6 | -------------------------------------------------------------------------------- /tests/test_data/packages/snowman-0.1/debian/control: -------------------------------------------------------------------------------- 1 | Source: snowman 2 | Section: misc 3 | Priority: optional 4 | Maintainer: Snowman ☃ 5 | Build-Depends: debhelper-compat (= 12) 6 | Rules-Requires-Root: no 7 | 8 | Package: snowman 9 | Architecture: all 10 | Depends: ${misc:Depends} 11 | Description: a ☃ package 12 | a ☃ package 13 | -------------------------------------------------------------------------------- /tests/test_data/packages/snowman-0.1/debian/copyright: -------------------------------------------------------------------------------- 1 | This is a package by Snowman ☃ 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/snowman-0.1/debian/rules: -------------------------------------------------------------------------------- 1 | #! /usr/bin/make -f 2 | %: 3 | dh $@ 4 | -------------------------------------------------------------------------------- /tests/test_data/packages/snowman-0.1/debian/snowman.install: -------------------------------------------------------------------------------- 1 | some-file usr/share/snowman-☃ 2 | -------------------------------------------------------------------------------- /tests/test_data/packages/snowman-0.1/some-file: -------------------------------------------------------------------------------- 1 | some-text ☃ 2 | -------------------------------------------------------------------------------- /tests/test_data/samplerepo/dummy/dists/testing/main/binary-all/Packages.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/samplerepo/dummy/dists/testing/main/binary-all/Packages.xz -------------------------------------------------------------------------------- /tests/test_data/samplerepo/dummy/dists/testing/main/binary-amd64/Packages.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/samplerepo/dummy/dists/testing/main/binary-amd64/Packages.xz -------------------------------------------------------------------------------- /tests/test_data/samplerepo/dummy/dists/testing/main/source/Sources.xz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lkhq/laniakea/d1d6aca5e2f0fc10ffa720381d63b879a636e5ae/tests/test_data/samplerepo/dummy/dists/testing/main/source/Sources.xz -------------------------------------------------------------------------------- /tests/test_data/samplerepo/dummy/dists/unstable: -------------------------------------------------------------------------------- 1 | testing/ -------------------------------------------------------------------------------- /tests/test_data/spears/HeidiResult: -------------------------------------------------------------------------------- 1 | pkgnew 0.1-1 source misc 2 | snowman 0.1-1 source misc 3 | package 0.2-1 source misc 4 | nonfree-package 0.1-1 source non-free/misc 5 | package 0.1-1 source misc 6 | pkgnew 0.1-3 source misc 7 | main-contrib-with-debug 0.1-1 source misc 8 | pkg-any1 0.1-3 amd64 misc 9 | pkg-any3 0.1-2 amd64 misc 10 | package 0.1-1 all misc 11 | package 0.2-1 all misc 12 | pkg-all2 0.1-3 all misc 13 | pkg-any1 0.1-2 amd64 misc 14 | pkg-any4 0.1-2 amd64 misc 15 | pkg-any2 0.1-2 amd64 misc 16 | pkg-all1 0.1-3 all misc 17 | pkg-all3 0.1-3 all misc 18 | pkg-any3 0.1-3 amd64 misc 19 | pkg-any2 0.1-3 amd64 misc 20 | main-package 0.1-1 all misc 21 | -------------------------------------------------------------------------------- /tests/test_data/spears/heidi-current: -------------------------------------------------------------------------------- 1 | snowman 0.1-1 source 2 | package 0.2-1 source 3 | nonfree-package 0.1-1 source 4 | pkgnew 0.1-3 source 5 | main-contrib-with-debug 0.1-1 source 6 | pkg-any1 0.1-3 amd64 7 | package 0.2-1 all 8 | pkg-all2 0.1-3 all 9 | pkg-all1 0.1-3 all 10 | pkg-all3 0.1-3 all 11 | pkg-any3 0.1-3 amd64 12 | pkg-any2 0.1-3 amd64 13 | main-package 0.1-1 all 14 | -------------------------------------------------------------------------------- /tests/test_flatpakrepo.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Copyright (C) 2018-2022 Matthias Klumpp 4 | # 5 | # SPDX-License-Identifier: LGPL-3.0+ 6 | 7 | from tempfile import TemporaryDirectory 8 | 9 | from laniakea.db import FlatpakRepository 10 | from laniakea.flatpak_util import FlatpakUtil 11 | 12 | 13 | def test_flatpak_init_repo(localconfig, samples_dir): 14 | '''Check if we can create an empty Flatpak repo''' 15 | 16 | repo = FlatpakRepository('laniakea_test') 17 | repo.collection_id = 'org.example.LaniakeaUnittest' 18 | repo.title = 'Laniakea Unit Test Repository' 19 | repo.comment = 'Just a test' 20 | repo.url_homepage = 'https://tanglu.org' 21 | repo.gpg_key_id = '8BB746C63FF5346326C19ABDEFD8BD07D224478F' 22 | repo.allowed_branches = ['stable', 'testing', 'edge'] 23 | repo.default_branch = 'stable' 24 | 25 | with TemporaryDirectory(prefix='lkunittest-') as tmpdir: 26 | fputil = FlatpakUtil() 27 | fputil.init_repo(repo, tmpdir) 28 | --------------------------------------------------------------------------------