From 412a7bae16e30764f3dc2c843ee67a3d0cd57efb Mon Sep 17 00:00:00 2001 From: Kevin Veen-Birkenbach Date: Thu, 20 Mar 2025 00:23:35 +0100 Subject: [PATCH] Added helper functions for portfolio --- README.md | 135 +++++++++-------------- docker-compose.yml | 6 +- main.py | 260 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 315 insertions(+), 86 deletions(-) create mode 100755 main.py diff --git a/README.md b/README.md index 1c39b85..37b803e 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,22 @@ -# Portfolio CMS: Flask-based Portfolio ManagementπŸš€ -[![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) +```markdown +# Portfolio CMS: Flask-based Portfolio Management πŸš€ +[![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) This software allows individuals and institutions to set up an easy portfolio/landingpage/homepage to showcase their projects and online presence. It is highly customizable via a YAML configuration file. ## Features ✨ -- **Dynamic Navigation**: Easily create dropdown menus and nested links. -- **Customizable Cards**: Showcase your skills, projects, or services. -- **Cache Management**: Optimize your assets with automatic caching. -- **Responsive Design**: Beautiful on any device with Bootstrap. -- **Easy Configuration**: Update content using a YAML file. +- **Dynamic Navigation:** Easily create dropdown menus and nested links. +- **Customizable Cards:** Showcase your skills, projects, or services. +- **Cache Management:** Optimize your assets with automatic caching. +- **Responsive Design:** Beautiful on any device with Bootstrap. +- **Easy Configuration:** Update content using a YAML file. +- **Command Line Interface:** Manage Docker containers with the `portfolio` CLI. ## Access 🌐 -### Locale +### Local Access Access the application locally at [http://127.0.0.1:5000](http://127.0.0.1:5000). ## Getting Started 🏁 @@ -26,6 +28,8 @@ Access the application locally at [http://127.0.0.1:5000](http://127.0.0.1:5000) ### Installation πŸ› οΈ +#### Installation via git clone + 1. **Clone the repository:** ```bash git clone @@ -40,9 +44,40 @@ Access the application locally at [http://127.0.0.1:5000](http://127.0.0.1:5000) docker-compose up --build ``` -4. **Access your portfolio:** Open your browser and navigate to [http://localhost:5000](http://localhost:5000). +4. **Access your portfolio:** + Open your browser and navigate to [http://localhost:5000](http://localhost:5000). -## Configuration Guide πŸ”§ +### Installation via Kevin's Package Manager + +You can install the `portfolio` CLI using [Kevin's package manager](https://github.com/kevinveenbirkenbach/package-manager). Simply run: + +```bash +pkgmgr install portfolio +``` + +This will install the CLI tool, making it available system-wide. + +### Available Commands + +After installation, you can access the help information for the CLI by running: + +```bash +portfolio --help +``` + +This command displays detailed instructions on how to use the following commands: + +- **build:** Build the Docker image for the portfolio application. +- **up:** Start the application using docker-compose (with build). +- **down:** Stop and remove the Docker container. +- **run-dev:** Run the container in development mode with hot-reloading. +- **run-prod:** Run the container in production mode. +- **logs:** Display the logs of the running container. +- **dev:** Start the application in development mode using docker-compose. +- **prod:** Start the application in production mode using docker-compose. +- **cleanup:** Remove all stopped Docker containers to clean up your Docker environment. + +## YAML Configuration Guide πŸ”§ The portfolio is powered by a YAML configuration file (`config.yaml`). This file allows you to define the structure and content of your site, including cards, navigation, and company details. @@ -95,77 +130,11 @@ company: ### Understanding the `children` Key πŸ” -The `children` key allows hierarchical nesting of elements. Each child can itself have children, enabling the creation of multi-level navigation menus or grouped content. Example: - -```yaml -children: - - name: Parent Item - description: Parent description. - icon: - class: fa-solid fa-folder - children: - - name: Child Item - description: Child description. - icon: - class: fa-solid fa-file - url: https://example.com -``` - -This structure will render a parent menu or section containing nested child elements. Each child can be further customized with icons, descriptions, and links. +The `children` key allows hierarchical nesting of elements. Each child can itself have children, enabling the creation of multi-level navigation menus or grouped content. ### Understanding the `link` Key πŸ”— -The `link` key allows you to reference another part of the YAML configuration by its path. This is useful for avoiding duplication and maintaining consistency. Example: - -```yaml -children: - - name: Blog - description: My blog posts. - icon: - class: fa-solid fa-blog - url: https://example.com/blog - - name: Featured Blog - link: accounts.children[0].children[0] # References the "Blog" item above -``` - -In this example, `Featured Blog` will inherit all properties from the `Blog` item, including its name, description, and URL. This feature ensures that any updates to the `Blog` item are automatically reflected in all linked entries. - -## Administrate Docker 🐳 - -### Stop and Destroy -```bash -docker stop portfolio; docker rm portfolio -``` - -### Build -```bash -docker build -t application-portfolio . -``` - -### Run - -#### Run Development Environment -```bash -docker run -d -p 5000:5000 --name portfolio -v $(pwd)/app/:/app -e FLASK_APP=app.py -e FLASK_ENV=development application-portfolio -``` - -#### Run Production Environment -```bash -docker run -d -p 5000:5000 --name portfolio application-portfolio -``` - -### Debug -```bash -docker logs -f portfolio -``` - -## Development Mode πŸ§‘β€πŸ’» - -To run the app in development mode with hot-reloading: - -```bash -FLASK_ENV=development docker-compose up -``` +The `link` key allows you to reference another part of the YAML configuration by its path, which helps avoid duplication and maintain consistency. ## Deployment 🚒 @@ -175,10 +144,10 @@ For production deployment, ensure to: - Secure your site with SSL/TLS. - Use a production-ready database if required. -## Author ✍️ - -This software was created by [Kevin Veen-Birkenbach](https://www.veen.world/). - ## License πŸ“œ -This project is licensed under the GNU Affero General Public License Version 3. See the [LICENSE](./LICENSE) file for details. \ No newline at end of file +This project is licensed under the GNU Affero General Public License Version 3. See the [LICENSE](./LICENSE) file for details. + +## Author ✍️ + +This software was created by [Kevin Veen-Birkenbach](https://www.veen.world/). \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index b70b22d..46586f6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,10 +1,10 @@ services: - landingpage: + portfolio: build: context: . dockerfile: Dockerfile - image: application-landingpage - container_name: landingpage + image: application-portfolio + container_name: portfolio ports: - "5000:5000" volumes: diff --git a/main.py b/main.py new file mode 100755 index 0000000..a015482 --- /dev/null +++ b/main.py @@ -0,0 +1,260 @@ +#!/usr/bin/env python3 +""" +main.py - A CLI tool for managing the Portfolio CMS Docker application. + +This script provides commands to build and run the Docker container for the +portfolio application. It mimics the functionality of a Makefile with additional +explanatory text using argparse. + +Commands: + build - Build the Docker image. + up - Start the application using docker-compose (with build). + down - Stop and remove the running container. + run-dev - Run the container in development mode (with hot-reloading). + run-prod - Run the container in production mode. + logs - Display the logs of the running container. + dev - Start the application in development mode using docker-compose. + prod - Start the application in production mode using docker-compose. + cleanup - Remove all stopped containers. +""" + +import argparse +import subprocess +import sys +import os + +def run_command(command, dry_run=False): + """Utility function to run a shell command.""" + print(f"Executing: {' '.join(command)}") + if dry_run: + print("Dry run enabled: command not executed.") + return + try: + subprocess.check_call(command) + except subprocess.CalledProcessError as e: + print(f"Error: Command failed with exit code {e.returncode}") + sys.exit(e.returncode) + +def build(args): + """ + Build the Docker image for the portfolio application. + + Command: + docker build -t application-portfolio . + + This command creates a Docker image named 'application-portfolio' + from the Dockerfile in the current directory. + """ + command = ["docker", "build", "-t", "application-portfolio", "."] + run_command(command, args.dry_run) + +def up(args): + """ + Start the application using docker-compose with build. + + Command: + docker-compose up --build + + This command uses docker-compose to build (if necessary) and start + all defined services. It is useful for quickly starting your + development or production environment. + """ + command = ["docker-compose", "up", "--build"] + run_command(command, args.dry_run) + +def down(args): + """ + Stop and remove the Docker container named 'portfolio'. + + Commands: + docker stop portfolio + docker rm portfolio + + These commands stop the running container and remove it from your Docker host. + The '-' prefix is used to ignore errors if the container is not running. + """ + command_stop = ["docker", "stop", "portfolio"] + command_rm = ["docker", "rm", "portfolio"] + run_command(command_stop, args.dry_run) + run_command(command_rm, args.dry_run) + +def run_dev(args): + """ + Run the container in development mode with hot-reloading. + + Command: + docker run -d -p 5000:5000 --name portfolio -v $(pwd)/app/:/app \ + -e FLASK_APP=app.py -e FLASK_ENV=development application-portfolio + + This command starts the container in detached mode (-d), maps port 5000, + mounts the local 'app/' directory into the container, and sets environment + variables to enable Flask's development mode. + """ + current_dir = os.getcwd() + volume_mapping = f"{current_dir}/app/:/app" + command = [ + "docker", "run", "-d", + "-p", "5000:5000", + "--name", "portfolio", + "-v", volume_mapping, + "-e", "FLASK_APP=app.py", + "-e", "FLASK_ENV=development", + "application-portfolio" + ] + run_command(command, args.dry_run) + +def run_prod(args): + """ + Run the container in production mode. + + Command: + docker run -d -p 5000:5000 --name portfolio application-portfolio + + This command starts the container in detached mode, mapping port 5000, + and runs the production version of the portfolio application. + """ + command = [ + "docker", "run", "-d", + "-p", "5000:5000", + "--name", "portfolio", + "application-portfolio" + ] + run_command(command, args.dry_run) + +def logs(args): + """ + Display the logs of the 'portfolio' container. + + Command: + docker logs -f portfolio + + This command follows the logs (using -f) of the running container, + which is helpful for debugging and monitoring. + """ + command = ["docker", "logs", "-f", "portfolio"] + run_command(command, args.dry_run) + +def dev(args): + """ + Run the application in development mode using docker-compose. + + Command: + FLASK_ENV=development docker-compose up -d + + This command sets the FLASK_ENV environment variable to 'development' + and starts the application using docker-compose, enabling hot-reloading. + """ + env = os.environ.copy() + env["FLASK_ENV"] = "development" + command = ["docker-compose", "up", "-d"] + print("Setting FLASK_ENV=development") + run_command(command, args.dry_run) + +def prod(args): + """ + Run the application in production mode using docker-compose. + + Command: + docker-compose up --build + + This command builds the Docker image if needed and starts the application + using docker-compose for a production environment. + """ + command = ["docker-compose", "up", "--build"] + run_command(command, args.dry_run) + +def cleanup(args): + """ + Remove all stopped Docker containers. + + Command: + docker container prune -f + + This command cleans up your Docker environment by forcefully removing + all stopped containers. It is useful to reclaim disk space and remove + unused containers. + """ + command = ["docker", "container", "prune", "-f"] + run_command(command, args.dry_run) + +def main(): + parser = argparse.ArgumentParser( + description="CLI tool to manage the Portfolio CMS Docker application." + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Print the commands without executing them." + ) + + subparsers = parser.add_subparsers( + title="Commands", + description="Available commands to manage the application", + dest="command" + ) + + # Build command + parser_build = subparsers.add_parser( + "build", help="Build the Docker image." + ) + parser_build.set_defaults(func=build) + + # Up command (docker-compose up) + parser_up = subparsers.add_parser( + "up", help="Start the application using docker-compose (with build)." + ) + parser_up.set_defaults(func=up) + + # Down command + parser_down = subparsers.add_parser( + "down", help="Stop and remove the Docker container." + ) + parser_down.set_defaults(func=down) + + # Run-dev command + parser_run_dev = subparsers.add_parser( + "run-dev", help="Run the container in development mode (with hot-reloading)." + ) + parser_run_dev.set_defaults(func=run_dev) + + # Run-prod command + parser_run_prod = subparsers.add_parser( + "run-prod", help="Run the container in production mode." + ) + parser_run_prod.set_defaults(func=run_prod) + + # Logs command + parser_logs = subparsers.add_parser( + "logs", help="Display the logs of the running container." + ) + parser_logs.set_defaults(func=logs) + + # Dev command (docker-compose with FLASK_ENV) + parser_dev = subparsers.add_parser( + "dev", help="Start the application in development mode using docker-compose." + ) + parser_dev.set_defaults(func=dev) + + # Prod command (docker-compose production) + parser_prod = subparsers.add_parser( + "prod", help="Start the application in production mode using docker-compose." + ) + parser_prod.set_defaults(func=prod) + + # Cleanup command + parser_cleanup = subparsers.add_parser( + "cleanup", help="Remove all stopped Docker containers." + ) + parser_cleanup.set_defaults(func=cleanup) + + args = parser.parse_args() + + if args.command is None: + parser.print_help() + sys.exit(1) + + # Execute the chosen subcommand function + args.func(args) + +if __name__ == "__main__": + main()