diff --git a/.github/workflows/test-container.yml b/.github/workflows/test-container.yml new file mode 100644 index 00000000..364d9b02 --- /dev/null +++ b/.github/workflows/test-container.yml @@ -0,0 +1,31 @@ +name: Build & Test Container + +on: + push: + branches: + - master + pull_request: + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build Docker image + run: | + docker build -t cymais:latest . + + - name: Clean build artifacts + run: | + docker run --rm cymais:latest cymais make clean + + - name: Generate project outputs + run: | + docker run --rm cymais:latest cymais make build + + - name: Run tests + run: | + docker run --rm cymais:latest cymais make test diff --git a/.github/workflows/test-on-arch.yml b/.github/workflows/test-on-arch.yml deleted file mode 100644 index 1befafe6..00000000 --- a/.github/workflows/test-on-arch.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Build & Test on Arch Linux - -on: - push: - branches: [ master ] - pull_request: - -jobs: - build-and-test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Build & Test in Arch Linux Container - uses: addnab/docker-run-action@v3 - with: - image: archlinux:latest - options: -v ${{ github.workspace }}:/workspace -w /workspace - run: | - pacman -Sy --noconfirm base-devel git python python-pip docker make - make build - make test diff --git a/Dockerfile b/Dockerfile index 759cc4cc..1cb2c4e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,11 +42,23 @@ RUN git clone https://github.com/kevinveenbirkenbach/package-manager.git $PKGMGR # 5) Ensure pkgmgr venv bin and user-local bin are on PATH ENV PATH="$PKGMGR_VENV/bin:/root/.local/bin:${PATH}" -# 6) Install CyMaIS (using HTTPS cloning mode) +# 6) Copy local CyMaIS source into the image for override +COPY . /opt/cymais-src + +# 7) Install CyMaIS via pkgmgr (clone-mode https) RUN pkgmgr install cymais --clone-mode https -# 7) Symlink the cymais CLI into /usr/local/bin so ENTRYPOINT works -RUN ln -s /root/.local/bin/cymais /usr/local/bin/cymais +# 8) Override installed CyMaIS with local source and clean ignored files +RUN CMAIS_PATH=$(pkgmgr path cymais) && \ + rm -rf "$CMAIS_PATH"/* && \ + cp -R /opt/cymais-src/* "$CMAIS_PATH"/ && \ + cd "$CMAIS_PATH" && \ + make clean + +# 9) Symlink the cymais script into /usr/local/bin so ENTRYPOINT works +RUN CMAIS_PATH=$(pkgmgr path cymais) && \ + ln -sf "$CMAIS_PATH"/main.py /usr/local/bin/cymais && \ + chmod +x /usr/local/bin/cymais ENTRYPOINT ["cymais"] CMD ["--help"] diff --git a/Makefile b/Makefile index d1ee6a62..66dbe7af 100644 --- a/Makefile +++ b/Makefile @@ -22,8 +22,8 @@ EXTRA_USERS := $(shell \ .PHONY: build install test clean: - @echo "Removing not tracked git files" - git clean -fdx + @echo "Removing ignored git files" + git clean -fdX tree: @echo Generating Tree diff --git a/README.md b/README.md index 1cd67162..7a14765c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # IT-Infrastructure Automation Framework 🚀 -[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-blue?logo=github)](https://github.com/sponsors/kevinveenbirkenbach) [![Patreon](https://img.shields.io/badge/Support-Patreon-orange?logo=patreon)](https://www.patreon.com/c/kevinveenbirkenbach) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20Coffee-Funding-yellow?logo=buymeacoffee)](https://buymeacoffee.com/kevinveenbirkenbach) [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue?logo=paypal)](https://s.veen.world/paypaldonate) +[![GitHub Sponsors](https://img.shields.io/badge/Sponsor-GitHub%20Sponsors-blue?logo=github)](https://github.com/sponsors/kevinveenbirkenbach) [![Patreon](https://img.shields.io/badge/Support-Patreon-orange?logo=patreon)](https://www.patreon.com/c/kevinveenbirkenbach) [![Buy Me a Coffee](https://img.shields.io/badge/Buy%20me%20a%20Coffee-Funding-yellow?logo=buymeacoffee)](https://buymeacoffee.com/kevinveenbirkenbach) [![PayPal](https://img.shields.io/badge/Donate-PayPal-blue?logo=paypal)](https://s.veen.world/paypaldonate) [![Build Status](https://github.com/kevinveenbirkenbach/cymais/actions/workflows/test-container.yml/badge.svg?branch=master)](https://github.com/kevinveenbirkenbach/cymais/actions/workflows/test-container.yml?query=branch%3Amaster) [![CyMaIS.Cloud](https://img.shields.io/badge/CyMaIS-%2ECloud-000000?labelColor=004B8D&style=flat&borderRadius=8)](https://cymais.cloud) + + --- @@ -63,6 +65,20 @@ Give CyMaIS a spin at [CyMaIS.cloud](httpy://cymais.cloud) – sign up in second ``` --- +### Setup with Docker🚢 + +Get CyMaIS up and running inside Docker in just a few steps. For detailed build options and troubleshooting, see the [Docker Guide](docs/Docker.md). + +```bash +# 1. Build the Docker image: the Docker image: +docker build -t cymais:latest . + +# 2. Run the CLI interactively: +docker run --rm -it cymais:latest cymais --help +``` + +--- + ## License ⚖️ CyMaIS is distributed under the **CyMaIS NonCommercial License**. Please see [LICENSE.md](LICENSE.md) for full terms. diff --git a/cli/make.py b/cli/make.py new file mode 100644 index 00000000..76e8fbaf --- /dev/null +++ b/cli/make.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +""" +CLI wrapper for Makefile targets within CyMaIS. +Invokes `make` commands in the project root directory. +""" +import argparse +import os +import subprocess +import sys + + +def main(): + parser = argparse.ArgumentParser( + prog='cymais make', + description='Run Makefile targets for CyMaIS project' + ) + parser.add_argument( + 'targets', + nargs=argparse.REMAINDER, + help='Make targets and options to pass to `make`' + ) + args = parser.parse_args() + + # Default to 'build' if no target is specified + make_args = args.targets or ['build'] + + # Determine repository root (one level up from cli/) + script_dir = os.path.dirname(os.path.realpath(__file__)) + repo_root = os.path.abspath(os.path.join(script_dir, os.pardir)) + + # Check for Makefile + makefile_path = os.path.join(repo_root, 'Makefile') + if not os.path.isfile(makefile_path): + print(f"Error: Makefile not found in {repo_root}", file=sys.stderr) + sys.exit(1) + + # Invoke make in repo root + cmd = ['make'] + make_args + try: + result = subprocess.run(cmd, cwd=repo_root) + sys.exit(result.returncode) + except FileNotFoundError: + print("Error: 'make' command not found. Please install make.", file=sys.stderr) + sys.exit(1) + except KeyboardInterrupt: + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/docs/Docker.md b/docs/Docker.md new file mode 100644 index 00000000..5902e049 --- /dev/null +++ b/docs/Docker.md @@ -0,0 +1,124 @@ +# Docker Build Guide 🚢 + +This guide explains how to build the **CyMaIS** Docker image with advanced options to avoid common issues (e.g. mirror timeouts) and control build caching. + +--- + +## 1. Enable BuildKit (Optional but Recommended) + +Modern versions of Docker support **BuildKit**, which speeds up build processes and offers better caching. + +```bash +# On your host, enable BuildKit for the current shell session: +export DOCKER_BUILDKIT=1 +``` + +> **Note:** You only need to set this once per terminal session. + +--- + +## 2. Build Arguments Explained + +When you encounter errors like: + +```text +:: Synchronizing package databases... +error: failed retrieving file 'core.db' from geo.mirror.pkgbuild.com : Connection timed out after 10002 milliseconds +error: failed to synchronize all databases (failed to retrieve some files) +``` + +it usually means the default container network cannot reach certain Arch Linux mirrors. To work around this, use: + +* `--network=host` + Routes all build-time network traffic through your host’s network stack. + +* `--no-cache` + Forces a fresh build of every layer by ignoring Docker’s layer cache. Useful if you suspect stale cache entries. + +--- + +## 3. Recommended Build Command + +```bash +# 1. (Optional) Enable BuildKit +export DOCKER_BUILDKIT=1 + +# 2. Build with host networking and no cache +docker build \ + --network=host \ + --no-cache \ + -t cymais:latest \ + . +``` + +**Flags:** + +* `--network=host` + Ensures all `pacman -Syu` and other network calls hit your host network directly—eliminating mirror connection timeouts. + +* `--no-cache` + Guarantees that changes to package lists or dependencies are picked up immediately by rebuilding every layer. + +* `-t cymais:latest` + Tags the resulting image as `cymais:latest`. + +--- + +## 4. Running the Container + +Once built, you can run CyMaIS as usual: + +```bash +docker run --rm -it \ + -v "$(pwd)":/opt/cymais \ + -w /opt/cymais \ + cymais:latest cymais --help +``` + +Mount any host directory into `/opt/cymais/logs` to persist logs across runs. + +--- + +## 5. Further Troubleshooting + +* **Mirror selection:** If you still see slow or unreachable mirrors, consider customizing `/etc/pacman.d/mirrorlist` in a local Docker stage or on your host to prioritize faster mirrors. + +* **Firewall or VPN:** Ensure your host’s firewall or VPN allows outgoing connections on port 443/80 to Arch mirror servers. + +* **Docker daemon config:** On some networks, you may need to configure Docker’s daemon proxy settings under `/etc/docker/daemon.json`. + +## 6. Live Development via Volume Mount + +The CyMaIS installation inside the container always resides at: + +``` +/root/Repositories/github.com/kevinveenbirkenbach/cymais +``` + +To apply code changes without rebuilding the image, mount your local installation directory into that static path: + +```bash +# 1. Determine the CyMaIS install path on your host +CMAIS_PATH=$(pkgmgr path cymais) + +# 2. Launch the container with a bind mount: +docker run --rm -it \ + -v "${CMAIS_PATH}:/root/Repositories/github.com/kevinveenbirkenbach/cymais" \ + -w "/root/Repositories/github.com/kevinveenbirkenbach/cymais" \ + cymais:latest cymais make build +``` + +Or, to test the CLI help interactively: + +```bash +docker run --rm -it \ + -v "${CMAIS_PATH}:/root/Repositories/github.com/kevinveenbirkenbach/cymais" \ + -w "/root/Repositories/github.com/kevinveenbirkenbach/cymais" \ + cymais:latest --help +``` + +Any edits you make in `${CMAIS_PATH}` on your host are immediately reflected inside the container, eliminating the need for repeated `docker build` cycles. + +--- + +With these options, your Docker builds should complete reliably, even in restrictive network environments. Happy building! 🚀 diff --git a/main.py b/main.py index ab6d8be1..33d0d49a 100755 --- a/main.py +++ b/main.py @@ -18,7 +18,24 @@ except ImportError: def __getattr__(self, name): return '' Fore = Back = Style = Dummy() -from cli.sounds import Sound # ensure Sound imported +_IN_DOCKER = os.path.exists('/.dockerenv') + +if _IN_DOCKER: + class Quiet: + @staticmethod + def play_start_sound(): pass + @staticmethod + def play_cymais_intro_sound(): pass + @staticmethod + def play_finished_successfully_sound(): pass + @staticmethod + def play_finished_failed_sound(): pass + @staticmethod + def play_warning_sound(): pass + + Sound = Quiet +else: + from utils.sounds import Sound def color_text(text, color): diff --git a/cli/sounds.py b/utils/sounds.py similarity index 100% rename from cli/sounds.py rename to utils/sounds.py