diff --git a/README.es.md b/README.es.md index ad45b9c..b9d47c4 100644 --- a/README.es.md +++ b/README.es.md @@ -4,414 +4,57 @@ ![Banner de Struct](extras/banner.png) -> [!WARNING] -> Este proyecto aún está en desarrollo y puede contener errores. Úsalo bajo tu propio riesgo. +STRUCT automatiza la creación de estructuras de proyectos a partir de plantillas YAML. Está orientado a desarrolladores y equipos DevOps que buscan un andamiaje reproducible de forma sencilla. -## 📄 Tabla de Contenidos +## Características -- [Introducción](#-introducción) -- [Características](#-características) -- [Instalación](#️-instalación) - - [Usando pip](#usando-pip) - - [Desde el código fuente](#desde-el-código-fuente) - - [Usando Docker](#usando-docker) -- [Inicio Rápido](#-inicio-rápido) -- [Uso](#-uso) -- [Configuración YAML](#-configuración-yaml) -- [Esquema YAML](#-esquema-yaml) -- [Desarrollo](#-desarrollo) -- [Licencia](#-licencia) -- [Financiamiento](#-financiamiento) -- [Contribuyendo](#-contribuyendo) -- [Agradecimientos](#-agradecimientos) -- [Problemas Conocidos](#-problemas-conocidos) +- Definición de estructuras con YAML +- Variables de plantilla con soporte interactivo +- Permisos de archivos personalizados +- Inclusión de archivos remotos +- Estrategias para gestionar archivos existentes +- Modo de prueba y validación +- Registro detallado -## 📦 Introducción +## Inicio rápido -STRUCT es un script potente y flexible diseñado para automatizar la creación de estructuras de proyectos basadas en configuraciones YAML. Admite variables de plantilla, permisos de archivos personalizados, obtención de contenido remoto y múltiples estrategias de manejo de archivos para optimizar tu proceso de configuración de desarrollo. - -Está dirigido a desarrolladores, ingenieros DevOps y cualquier persona que quiera automatizar la creación de estructuras de proyectos. Puede usarse para generar código de plantilla, archivos de configuración, documentación y más. - -## ✨ Características - -- **Configuración YAML**: Define la estructura de tu proyecto en un simple archivo YAML. -- **Variables de Plantilla**: Usa marcadores de posición en tu configuración y reemplázalos con valores reales en tiempo de ejecución. También admite filtros personalizados de Jinja2 y modo interactivo para completar las variables. -- **Permisos de Archivos Personalizados**: Establece permisos personalizados para tus archivos directamente desde la configuración YAML. -- **Obtención de Contenido Remoto**: Incluye contenido de archivos remotos especificando sus URLs. -- **Estrategias de Manejo de Archivos**: Elige entre múltiples estrategias (sobrescribir, omitir, añadir, renombrar, respaldar) para gestionar archivos existentes. -- **Ejecutar en Seco**: Previsualiza las acciones sin hacer cambios en tu sistema de archivos. -- **Validación de Configuración**: Asegura que tu configuración YAML es válida antes de ejecutar el script. -- **Registro Detallado**: Obtén registros detallados de las acciones del script para una fácil depuración y monitoreo. - -## 🛠️ Instalación - -### Usando pip - -Puedes instalar STRUCT usando pip: +Instalación con pip: ```sh pip install git+https://github.com/httpdss/struct.git ``` -### Desde el código fuente - -Alternativamente, puedes clonar el repositorio e instalarlo localmente. Consulta la sección [Desarrollo](#-desarrollo) para más detalles. - -### Usando Docker - -Puedes usar la imagen de Docker para ejecutar el script sin instalarlo en tu sistema. Consulta la sección [Inicio Rápido](#-inicio-rápido) para más detalles. - -## 🐳 Inicio Rápido - -### Inicio Rápido Usando Docker - -1. Crea un archivo de configuración YAML para la estructura de tu proyecto. Consulta una configuración de ejemplo [aquí](./example/structure.yaml). -2. Ejecuta el siguiente comando para generar la estructura del proyecto: +O mediante la imagen Docker: ```sh docker run \ -v $(pwd):/workdir \ -u $(id -u):$(id -g) \ - ghcr.io/httpdss/struct:main \ + ghcr.io/httpdss/struct:main generate \ /workdir/example/structure.yaml \ /workdir/example_output ``` -### Inicio Rápido Usando Docker Alpine - -Para pruebas, puedes ejecutar un contenedor Docker de Alpine e instalar el script dentro de él: - -```sh -docker run -it --entrypoint="" python:3.10-alpine sh -l -``` - -Dentro del contenedor: - -```sh -apk add python-pip git vim -pip install git+https://github.com/httpdss/struct.git -mkdir example -cd example/ -touch structure.yaml -vim structure.yaml # copia el contenido de la carpeta de ejemplo -struct structure.yaml . -``` - -## 📝 Uso - -Ejecuta el script con el siguiente comando usando uno de los siguientes subcomandos: - -- `generate`: Genera la estructura del proyecto basada en la configuración YAML. -- `validate`: Valida la configuración YAML para asegurarte de que sea válida. -- `info`: Muestra información sobre el script y sus dependencias. -- `list`: Lista las estructuras disponibles. - -Para más información, ejecuta el script con la opción `-h` o `--help` (esto también está disponible para cada subcomando): - -```sh -struct -h -``` - -### Ejemplo Simple - -```sh -struct generate terraform-module ./mi-modulo-terraform -``` - -### Ejemplo Más Completo - -```sh -struct generate \ - --log=DEBUG \ - --dry-run \ - --vars="project_name=MiProyecto,author_name=JuanPerez" \ - --backup=/ruta/al/respaldo \ - --file-strategy=rename \ - --log-file=/ruta/al/archivo_de_registro.log \ - terraform-module \ - ./mi-modulo-terraform - -``` - -## 📄 Configuración YAML - -Aquí tienes un ejemplo de un archivo de configuración YAML: - -```yaml -files: - - README.md: - content: | - # {{@ project_name @}} - This is a template repository. - - script.sh: - permissions: '0777' - content: | - #!/bin/bash - echo "Hello, {{@ author_name @}}!" - - LICENSE: - file: https://raw.githubusercontent.com/nishanths/license/master/LICENSE - - archivo_remoto.txt: - file: file:///ruta/al/archivo/local.txt - - archivo_github.py: - file: github://owner/repo/branch/path/to/file.py - - archivo_github_https.py: - file: githubhttps://owner/repo/branch/path/to/file.py - - archivo_github_ssh.py: - file: githubssh://owner/repo/branch/path/to/file.py - - archivo_s3.txt: - file: s3://bucket_name/key - - archivo_gcs.txt: - file: gs://bucket_name/key - - src/main.py: - content: | - print("Hello, World!") -folders: - - .devops/modules/mod1: - struct: terraform/module - - .devops/modules/mod2: - struct: terraform/module - with: - module_name: mymod2 - - ./: - struct: - - docker-files - - project/go -variables: - - project_name: - description: "The name of the project" - default: "MyProject" - type: string - - author_name: - description: "The name of the author" - type: string - default: "John Doe" -``` - -### Variables de plantilla - -Puedes usar variables de plantilla en tu archivo de configuración encerrándolas entre `{{@` y `@}}`. Por ejemplo, `{{@ project_name @}}` será reemplazado con el valor de la variable `project_name` en tiempo de ejecución. Si las variables no se proporcionan en la línea de comandos, se solicitarán interactivamente. - -Si necesitas definir bloques, puedes usar la notación de inicio de bloque `{%@` y la notación de final de bloque `%@}`. - -Para definir comentarios, puedes usar la notación de inicio de comentario `{#@` y la notación de fin de comentario `@#}`. - -#### Variables de plantilla predeterminadas - -- `file_name`: El nombre del archivo que se está procesando. -- `file_directory`: El nombre del directorio del archivo que se está procesando. - -#### Variables de plantilla interactivo - -Si no proporcionas todas las variables en la línea de comandos, se solicitarán interactivamente. - -La struct definida debe incluir las variables en una seccion de `variables` con la siguiente estructura: - -```yaml -variables: - - variable_name: - description: "Descripción de la variable" - type: string - default: "Valor predeterminado" -``` - -como puedes ver, cada variable debe tener una descripción, un tipo y un valor predeterminado (opcional). Este valor predeterminado se usará si no se proporciona la variable en la línea de comandos. - -#### Filtros personalizados de Jinja2 - -##### `latest_release` - -Este filtro obtiene la versión más reciente de una release en un repositorio de GitHub. Toma el nombre del repositorio como argumento. - -```yaml -files: - - README.md: - content: | - # MyProject - Latest release: {{@ "httpdss/struct" | latest_release @}} -``` - -Esto utiliza PyGithub para obtener la última release del repositorio, por lo que configurar la variable de entorno `GITHUB_TOKEN` te dará acceso a repositorios privados. - -Si ocurre un error en el proceso, el filtro devolverá `LATEST_RELEASE_ERROR`. - -NOTA: puedes usar este filtro para obtener la última versión de un proveedor de Terraform. Por ejemplo, para obtener la última versión del proveedor `aws`, puedes usar `{{@ "hashicorp/terraform-provider-aws" | latest_release @}}` o el proveedor de datadog `{{@ "DataDog/terraform-provider-datadog" | latest_release @}}`. - -##### `slugify` - -Este filtro convierte una cadena en un slug. Toma un argumento opcional para especificar el carácter separador (el valor predeterminado es `-`). - -```yaml -files: - - README.md: - content: | - # {{@ project_name @}} - This is a template repository. - slugify project_name: {{@ project_name | slugify @}} -``` - -##### `default_branch` - -Este filtro obtiene el nombre de la rama predeterminada de un repositorio de GitHub. Toma el nombre del repositorio como argumento. - -```yaml -files: - - README.md: - content: | - # MyProject - Default branch: {{@ "httpdss/struct" | default_branch @}} -``` - -### Cláusula `with` - -La cláusula `with` te permite pasar variables adicionales a estructuras anidadas. Estas variables se fusionarán con las variables globales y se pueden usar dentro de la estructura anidada. - -Ejemplo: - -```yaml -folders: - - .devops/modules/mod1: - struct: terraform/module - - .devops/modules/mod2: - struct: terraform/module - with: - module_name: mymod2 -``` - -## 📝 Esquema YAML - -Para asegurar que tus archivos de configuración YAML cumplan con la estructura esperada, puedes usar el esquema JSON proporcionado. Esto ayuda a validar tus archivos YAML y proporciona autocompletado en editores compatibles como VSCode. - -### Configuración en VSCode - -1. Instala la [extensión YAML](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) para VSCode. -2. Añade la siguiente configuración a los ajustes de tu espacio de trabajo (`.vscode/settings.json`): - -```json -{ - "yaml.schemas": { - "https://raw.githubusercontent.com/httpdss/struct/refs/heads/main/struct-schema.json": ".struct.yaml" - } -} -``` - -Esta configuración asociará el esquema JSON con todos los archivos .struct.yaml en tu espacio de trabajo, proporcionando validación y autocompletado. - -## 🔄 Script de Disparador de GitHub - -El script `github-trigger.py` es una utilidad diseñada para activar el flujo de trabajo `run-struct` en todos los repositorios privados de una organización de GitHub que cumplan con ciertos criterios. Este script es especialmente útil para automatizar tareas en múltiples repositorios. - -### 📋 Características - -- Filtra repositorios por un tema específico (por ejemplo, `struct-enabled`). -- Verifica la existencia de un archivo `.struct.yaml` en la rama predeterminada del repositorio. -- Comprueba la presencia del archivo de flujo de trabajo `run-struct` en `.github/workflows/`. -- Activa el evento de despacho del flujo de trabajo en los repositorios elegibles. - -### 🚀 Uso - -Para usar el script, asegúrate de cumplir con los siguientes requisitos: - -1. Un token de acceso personal de GitHub válido con los permisos necesarios (configurado como la variable de entorno `GITHUB_TOKEN`). -2. La biblioteca `PyGithub` instalada (`pip install PyGithub`). - -Ejecuta el script con el siguiente comando: - -```sh -python3 scripts/github-trigger.py -``` - -#### Argumentos - -- ``: El nombre de la organización de GitHub. -- ``: El tema para filtrar los repositorios (por ejemplo, `struct-enabled`). - -#### Ejemplo - -```sh -export GITHUB_TOKEN=tu_token_de_acceso_personal -python3 scripts/github-trigger.py mi-org struct-enabled -``` - -### 🛠️ Cómo Funciona - -1. El script se conecta a la API de GitHub utilizando el token proporcionado. -2. Itera a través de todos los repositorios privados de la organización especificada. -3. Para cada repositorio: - - Verifica si el repositorio tiene el tema especificado. - - Comprueba la existencia de un archivo `.struct.yaml` en la rama predeterminada. - - Confirma la presencia del archivo de flujo de trabajo `run-struct`. - - Activa el evento de despacho del flujo de trabajo si se cumplen todas las condiciones. - -### ⚠️ Notas - -- Asegúrate de configurar la variable de entorno `GITHUB_TOKEN` antes de ejecutar el script. -- El token debe tener permisos suficientes para acceder a repositorios privados y activar flujos de trabajo. -- Los errores durante la ejecución (por ejemplo, archivos faltantes o permisos insuficientes) se registrarán en la consola. - -## 🪝 Ganchos de Pre-generación y Post-generación - -Puedes definir comandos de shell para ejecutar antes y después de la generación de la estructura usando las claves `pre_hooks` y `post_hooks` en tu configuración YAML. Son opcionales y te permiten automatizar pasos de preparación o limpieza. - -- **pre_hooks**: Lista de comandos de shell a ejecutar antes de la generación. Si algún comando falla (código distinto de cero), la generación se aborta. -- **post_hooks**: Lista de comandos de shell a ejecutar después de completar la generación. Si algún comando falla, se muestra un error. - -Ejemplo: - -```yaml -pre_hooks: - - echo "Preparando el entorno..." - - ./scripts/prep.sh - -post_hooks: - - echo "¡Generación completa!" - - ./scripts/cleanup.sh -files: - - README.md: - content: | - # Mi Proyecto -``` - -**Notas:** - -- La salida de los ganchos (stdout y stderr) se muestra en la terminal. -- Si un pre-hook falla, la generación se detiene. -- Si no se definen hooks, no ocurre nada extra. - -## 👩‍💻 Desarrollo - -Para comenzar con el desarrollo, sigue estos pasos: +## Documentación -- Clona el repositorio -- Crea un entorno virtual - -```sh -python3 -m venv .venv -source .venv/bin/activate -``` - -- Instala las dependencias - -```sh -pip install -r requirements.txt -pip install -r requirements.dev.txt -``` +La documentación completa se encuentra en la carpeta [docs](docs). Consulta allí las guías de instalación, uso y configuración detallada. -## 📜 Licencia +## Licencia -Este proyecto está licenciado bajo la Licencia MIT - consulta el archivo [LICENSE](LICENSE) para más detalles. +Este proyecto está bajo la Licencia MIT. Revisa el archivo [LICENSE](LICENSE) para más información. -## 💰 Financiamiento +## Financiamiento -Si encuentras este proyecto útil, considera apoyarlo a través de donaciones: [patreon/structproject](https://patreon.com/structproject) +Si este proyecto te resulta útil, considera apoyarlo mediante donaciones: [patreon/structproject](https://patreon.com/structproject) -## 🤝 Contribuyendo +## Contribuyendo -¡Las contribuciones son bienvenidas! Por favor, abre un issue o envía un pull request. +¡Las contribuciones son bienvenidas! Abre un issue o envía un pull request. -## 🙏 Agradecimientos +## Agradecimientos -Un agradecimiento especial a todos los contribuyentes que hicieron posible este proyecto. +Gracias a todas las personas que han contribuido a este proyecto. -## 🐞 Problemas Conocidos +## Problemas conocidos - [ ] TBD diff --git a/README.md b/README.md index 3e4b719..1d5b80d 100644 --- a/README.md +++ b/README.md @@ -4,64 +4,27 @@ ![Struct Banner](extras/banner.png) -## 📄 Table of Contents +STRUCT automates the creation of project structures from YAML templates. It is aimed at developers and DevOps engineers who want reproducible scaffolding with minimal effort. A Spanish translation is available in [README.es.md](README.es.md). -- [Introduction](#-introduction) -- [Features](#-features) -- [Installation](#️-installation) -- [Quick Start](#-quick-start) -- [Usage](#-usage) -- [YAML Configuration](#-yaml-configuration) -- [YAML Schema](#-yaml-schema) -- [GitHub Trigger Script](#-github-trigger-script) -- [Development](#-development) -- [License](#-license) -- [Funding](#-funding) -- [Contributing](#-contributing) -- [Acknowledgments](#-acknowledgments) -- [Known Issues](#-known-issues) +## Features -## 📦 Introduction +- Define project layouts using YAML +- Template variables with optional interactive prompts +- Custom file permissions +- Remote file inclusion (HTTP/GitHub/S3/GCS) +- Multiple strategies for existing files +- Dry-run mode and configuration validation +- Verbose logging -STRUCT is a powerful and flexible script designed to automate the creation of project structures based on YAML configurations. It supports template variables, custom file permissions, remote content fetching, and multiple file handling strategies to streamline your development setup process. +## Quick Start -This is targeted towards developers, DevOps engineers, and anyone who wants to automate the creation of project structures. It can be used to generate boilerplate code, configuration files, documentation, and more. - -## ✨ Features - -- **YAML Configuration**: Define your project structure in a simple YAML file. -- **Template Variables**: Use placeholders in your configuration and replace them with actual values at runtime. Also supports custom Jinja2 filters and interactive mode to fill in the variables. -- **Custom File Permissions**: Set custom permissions for your files directly from the YAML configuration. -- **Remote Content Fetching**: Include content from remote files by specifying their URLs. -- **File Handling Strategies**: Choose from multiple strategies (overwrite, skip, append, rename, backup) to manage existing files. -- **Dry Run**: Preview the actions without making any changes to your file system. -- **Configuration Validation**: Ensure your YAML configuration is valid before executing the script. -- **Verbose Logging**: Get detailed logs of the script's actions for easy debugging and monitoring. - -## 🛠️ Installation - -### Using pip - -You can install STRUCT using pip: +Install using pip: ```sh pip install git+https://github.com/httpdss/struct.git ``` -### From Source - -Alternatively, you can clone the repository and install it locally. See the [Development](#-development) section for more details. - -### Using Docker - -You can use the Docker image to run the script without installing it on your system. See the [Quick Start](#-quick-start) section for more details. - -## 🐳 Quick Start - -### Quick Start Using Docker - -1. Create a YAML configuration file for your project structure. See sample configuration [here](./example/structure.yaml). -2. Run the following command to generate the project structure: +Or run the Docker image: ```sh docker run \ @@ -72,396 +35,37 @@ docker run \ /workdir/example_output ``` -### Quick Start Using Docker Alpine - -For testing, you can run an alpine Docker container and install the script inside it: - -```sh -docker run -it --entrypoint="" python:3.10-alpine sh -l -``` - -Inside the container: - -```sh -apk add python-pip git vim -pip install git+https://github.com/httpdss/struct.git -mkdir example -cd example/ -touch structure.yaml -vim structure.yaml # copy the content from the example folder -struct generate structure.yaml . -``` - -## 📝 Usage - -Run the script with the following command using one of the following subcommands: - -- `generate`: Generate the project structure based on the YAML configuration. -- `validate`: Validate the YAML configuration file. -- `info`: Display information about the script and its dependencies. -- `list`: List the available structs - -For more information, run the script with the `-h` or `--help` option (this is also available for each subcommand): - -![Struct List](./docs/vhs/usage.gif) - -```sh -struct -h -``` - -### Simple Example - -```sh -struct generate terraform-module ./my-terraform-module -``` - -### More Complete Example - -```sh -struct generate \ - --log=DEBUG \ - --dry-run \ - --backup=/path/to/backup \ - --file-strategy=rename \ - --log-file=/path/to/logfile.log \ - terraform-module \ - ./my-terraform-module -``` - -## 📝 YAML Configuration - -### Configuration Properties - -When defining your project structure in the YAML configuration file, you can use various properties to control the behavior of the script. Here are the available properties: - -- **skip**: If set to `true`, the file or folder will be skipped and not created. -- **skip_if_exists**: If set to `true`, the file or folder will be skipped if it already exists. -- **permissions**: Set custom file permissions using a string representation of the octal value (e.g., `'0777'`). -- **content**: Define the content of the file directly in the YAML configuration. -- **file**: Specify a local or remote file to include. Supported protocols include `file://`, `http://`, `https://`, `github://`, `githubhttps://`, `githubssh://`, `s3://`, and `gs://`. - -Example: - -```yaml -files: - - README.md: - skip: true - content: | - # {{@ project_name @}} - This is a template repository. - - script.sh: - skip_if_exists: true - permissions: '0777' - content: | - #!/bin/bash - echo "Hello, {{@ author_name @}}!" - - LICENSE: - file: https://raw.githubusercontent.com/nishanths/license/master/LICENSE - - remote_file.txt: - file: file:///path/to/local/file.txt - - github_file.py: - file: github://owner/repo/branch/path/to/file.py - - github_https_file.py: - file: githubhttps://owner/repo/branch/path/to/file.py - - github_ssh_file.py: - file: githubssh://owner/repo/branch/path/to/file.py - - s3_file.txt: - file: s3://bucket_name/key - - gcs_file.txt: - file: gs://bucket_name/key - - src/main.py: - content: | - print("Hello, World!") -folders: - - .devops/modules/mod1: - struct: terraform/module - - .devops/modules/mod2: - struct: terraform/module - with: - module_name: mymod2 - - ./: - struct: - - docker-files - - project/go -variables: - - project_name: - description: "The name of the project" - default: "MyProject" - type: string - - author_name: - description: "The name of the author" - type: string - default: "John Doe" -``` - -These properties allow you to customize the behavior and content of the files and folders generated by the script, providing flexibility and control over your project structure. - -### Template variables - -You can use template variables in your configuration file by enclosing them in `{{@` and `@}}`. For example, `{{@ project_name @}}` will be replaced with the value of the `project_name` variable at runtime. If this are not set when running the script, it will prompt you to enter the value interactively. - -If you need to define blocks you can use starting block notation `{%@` and end block notation `%@}`. - -To define comments you can use the comment start notation `{#@` and end comment notation `@#}`. - -#### Default template variables - -- `file_name`: The name of the file being processed. -- `file_directory`: The name of the directory of file that is being processed. - -#### Interactive template variables - -If you don't provide a default value for a variable, the script will prompt you to enter the value interactively. - -The struct defined should define the variable on a specific section of the YAML file. For example: - -```yaml -variables: - - author_name: - description: "The name of the author" - type: string - default: "John Doe" -``` - -as you can see, the `author_name` variable is defined on the `variables` section of the YAML file. it includes a `description`, `type` and `default` value which is used if the user doesn't provide a value interactively. - -#### Custom Jinja2 filters - -##### `latest_release` - -This filter fetches the latest release version of a GitHub repository. It takes the repository name as an argument. - -```yaml -files: - - README.md: - content: | - # MyProject - Latest release: {{@ "httpdss/struct" | latest_release @}} -``` - -This uses PyGithub to fetch the latest release of the repository so setting the `GITHUB_TOKEN` environment variable will give you access to private repositories. - -If there is an error in the process, the filter will return `LATEST_RELEASE_ERROR`. - -NOTE: you can use this filter to get the latest release for a terraform provider. For example, to get the latest release of the `aws` provider, you can use `{{@ "hashicorp/terraform-provider-aws" | latest_release @}}` or datadog provider `{{@ "DataDog/terraform-provider-datadog" | latest_release @}}`. - -##### `slugify` - -This filter converts a string into a slug. It takes an optional argument to specify the separator character (default is `-`). - -```yaml -files: - - README.md: - content: | - # {{@ project_name @}} - This is a template repository. - slugify project_name: {{@ project_name | slugify @}} -``` - -##### `default_branch` - -This filter fetches the default branch name of a GitHub repository. It takes the repository name as an argument. - -```yaml -files: - - README.md: - content: | - # MyProject - Default branch: {{@ "httpdss/struct" | default_branch @}} -``` - -### `with` Clause - -The `with` clause allows you to pass additional variables to nested structures. These variables will be merged with the global variables and can be used within the nested structure. - -Example: - -```yaml -folders: - - .devops/modules/mod1: - struct: terraform/module - - .devops/modules/mod2: - struct: terraform/module - with: - module_name: mymod2 -``` - -## 📝 YAML Schema - -To ensure your YAML configuration files adhere to the expected structure, you can use the provided JSON schema. This helps in validating your YAML files and provides autocompletion in supported editors like VSCode. - -### Configuring VSCode - -1. Install the [YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml) for VSCode. -2. Add the following configuration to your workspace settings (`.vscode/settings.json`): - -```json -{ - "yaml.schemas": { - "https://raw.githubusercontent.com/httpdss/struct/main/extras/schema.json": ".struct.yaml" - } -} -``` - -This configuration will associate the JSON schema with all .struct.yaml files in your workspace, providing validation and autocompletion. - -## 🔄 GitHub Trigger Script - -The `github-trigger.py` script is a utility designed to trigger the `run-struct` workflow for all private repositories in a GitHub organization that meet specific criteria. This script is particularly useful for automating tasks across multiple repositories. - -### Features - -- Filters repositories by a specific topic (e.g., `struct-enabled`). -- Checks for the existence of a `.struct.yaml` file in the repository's default branch. -- Verifies the presence of the `run-struct` workflow file in `.github/workflows/`. -- Triggers the workflow dispatch event for eligible repositories. - -### Usage - -To use the script, ensure you have the following prerequisites: - -1. A valid GitHub Personal Access Token with the necessary permissions (set as the `GITHUB_TOKEN` environment variable). -2. The `PyGithub` library installed (`pip install PyGithub`). - -Run the script with the following command: - -```sh -python3 scripts/github-trigger.py -``` - -#### Arguments - -- ``: The name of the GitHub organization. -- ``: The topic to filter repositories by (e.g., `struct-enabled`). - -#### Example - -```sh -export GITHUB_TOKEN=your_personal_access_token -python3 scripts/github-trigger.py my-org struct-enabled -``` - -### How It Works - -1. The script connects to the GitHub API using the provided token. -2. It iterates through all private repositories in the specified organization. -3. For each repository: - - Checks if the repository has the specified topic. - - Verifies the existence of a `.struct.yaml` file in the default branch. - - Confirms the presence of the `run-struct` workflow file. - - Triggers the workflow dispatch event if all conditions are met. - -### Notes - -- Ensure the `GITHUB_TOKEN` environment variable is set before running the script. -- The token must have sufficient permissions to access private repositories and trigger workflows. -- Errors during execution (e.g., missing files or insufficient permissions) will be logged to the console. - -## 👩‍💻 Development - -To get started with development, follow these steps: - -- Clone the repository -- Create a virtual environment - -```sh -python3 -m venv .venv -source .venv/bin/activate -``` - -- Install the dependencies - -```sh -pip install -r requirements.txt -pip install -r requirements.dev.txt -``` - -## 🛠️ Command-Line Auto-Completion - -This project uses [argcomplete](https://kislyuk.github.io/argcomplete/) to provide command-line auto-completion for the `struct` script. Follow these steps to enable auto-completion: - -1. **Install `argcomplete`**: - - ```sh - pip install argcomplete - ``` - -2. **Enable global completion** for your shell. This step is usually done once: - - ```sh - activate-global-python-argcomplete - ``` - -3. **Register the script for auto-completion**. Add the following line to your shell's configuration file (e.g., `.bashrc`, `.zshrc`): - - ```sh - eval "$(register-python-argcomplete struct)" - ``` - -4. **Reload your shell configuration**: - - ```sh - source ~/.bashrc # or source ~/.zshrc for Zsh users - ``` - -After completing these steps, you should have auto-completion enabled for the `struct` script. You can test it by typing part of a command and pressing `Tab` to see the available options. - -```sh -struct -``` - -## Articles - -- [**Defining User Prompts on STRUCT: Harnessing GPT-4.1 for Scalable Project Scaffolding**](https://medium.com/@httpdss/defining-user-prompts-on-struct-harnessing-gpt-4-1-for-scalable-project-scaffolding-e6d3b4ec4701) -- [**Unlocking Developer Productivity with STRUCT: The Ultimate Open-Source Tool for Automated Project Structures**](https://blog.devops.dev/unlocking-developer-productivity-with-struct-the-ultimate-open-source-tool-for-automated-project-8bca9b5f40f9) -- [**Automating Project Structures with STRUCT and GitHub Actions**](https://medium.com/@httpdss/automating-project-structures-with-struct-and-github-actions-64e09c40c11e) -- [**Advanced STRUCT Tips: Working with Template Variables and Jinja2 Filters**](https://medium.com/@httpdss/advanced-struct-tips-working-with-template-variables-and-jinja2-filters-b239bf3145e4) - -## 🪝 Pre-generation and Post-generation Hooks - -You can define shell commands to run before and after structure generation using the `pre_hooks` and `post_hooks` keys in your YAML configuration. These are optional and allow you to automate setup or cleanup steps. - -- **pre_hooks**: List of shell commands to run before generation. If any command fails (non-zero exit), generation is aborted. -- **post_hooks**: List of shell commands to run after generation completes. If any command fails, an error is shown. - -Example: - -```yaml -pre_hooks: - - echo "Preparing environment..." - - ./scripts/prep.sh - -post_hooks: - - echo "Generation complete!" - - ./scripts/cleanup.sh -files: - - README.md: - content: | - # My Project -``` +## Documentation -**Notes:** +Complete documentation is available in the [docs](docs) directory: -- Output from hooks (stdout and stderr) is shown in the terminal. -- If a pre-hook fails, generation is halted. -- If no hooks are defined, nothing extra happens. +- [Installation](docs/installation.md) +- [Usage](docs/usage.md) +- [YAML configuration reference](docs/configuration.md) +- [YAML schema](docs/yaml_schema.md) +- [GitHub trigger script](docs/github_trigger_script.md) +- [Development](docs/development.md) +- [Command-line completion](docs/completion.md) +- [Hooks](docs/hooks.md) +- [Articles](docs/articles.md) +- [Available structures](docs/structures.md) -## 📜 License +## License -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. +This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. -## 💰 Funding +## Funding If you find this project helpful, please consider supporting it through donations: [patreon/structproject](https://patreon.com/structproject) -## 🤝 Contributing +## Contributing Contributions are welcome! Please open an issue or submit a pull request. -## 🙏 Acknowledgments +## Acknowledgments Special thanks to all the contributors who helped make this project possible. -## 🐞 Known Issues +## Known Issues - [ ] TBD diff --git a/docs/articles.md b/docs/articles.md new file mode 100644 index 0000000..20c3b68 --- /dev/null +++ b/docs/articles.md @@ -0,0 +1,6 @@ +# Articles + +- [Defining User Prompts on STRUCT: Harnessing GPT-4.1 for Scalable Project Scaffolding](https://medium.com/@httpdss/defining-user-prompts-on-struct-harnessing-gpt-4-1-for-scalable-project-scaffolding-e6d3b4ec4701) +- [Unlocking Developer Productivity with STRUCT: The Ultimate Open-Source Tool for Automated Project Structures](https://blog.devops.dev/unlocking-developer-productivity-with-struct-the-ultimate-open-source-tool-for-automated-project-8bca9b5f40f9) +- [Automating Project Structures with STRUCT and GitHub Actions](https://medium.com/@httpdss/automating-project-structures-with-struct-and-github-actions-64e09c40c11e) +- [Advanced STRUCT Tips: Working with Template Variables and Jinja2 Filters](https://medium.com/@httpdss/advanced-struct-tips-working-with-template-variables-and-jinja2-filters-b239bf3145e4) diff --git a/docs/completion.md b/docs/completion.md new file mode 100644 index 0000000..4d921c7 --- /dev/null +++ b/docs/completion.md @@ -0,0 +1,27 @@ +# Command-Line Auto-Completion + +STRUCT uses [argcomplete](https://kislyuk.github.io/argcomplete/) to provide auto-completion. + +1. Install `argcomplete`: + +```sh +pip install argcomplete +``` + +2. Enable global completion (usually done once): + +```sh +activate-global-python-argcomplete +``` + +3. Register the script in your shell configuration (e.g. `.bashrc` or `.zshrc`): + +```sh +eval "$(register-python-argcomplete struct)" +``` + +4. Reload your shell configuration: + +```sh +source ~/.bashrc # or ~/.zshrc for Zsh +``` diff --git a/docs/configuration.md b/docs/configuration.md new file mode 100644 index 0000000..98be926 --- /dev/null +++ b/docs/configuration.md @@ -0,0 +1,103 @@ +# YAML Configuration + +STRUCT reads a YAML file that describes the files and directories to create. Below are the available keys and options. + +## Configuration properties + +- **skip** – skip creation of a file or folder. +- **skip_if_exists** – only create if the path does not already exist. +- **permissions** – set custom file permissions (e.g. `'0777'`). +- **content** – inline file content. +- **file** – path or URL of a file to include. Supported protocols include `file://`, `http://`, `https://`, `github://`, `githubhttps://`, `githubssh://`, `s3://` and `gs://`. + +Example configuration: + +```yaml +files: + - README.md: + skip: true + content: | + # {{@ project_name @}} + This is a template repository. + - script.sh: + skip_if_exists: true + permissions: '0777' + content: | + #!/bin/bash + echo "Hello, {{@ author_name @}}!" + - LICENSE: + file: https://raw.githubusercontent.com/nishanths/license/master/LICENSE + - remote_file.txt: + file: file:///path/to/local/file.txt + - github_file.py: + file: github://owner/repo/branch/path/to/file.py + - github_https_file.py: + file: githubhttps://owner/repo/branch/path/to/file.py + - github_ssh_file.py: + file: githubssh://owner/repo/branch/path/to/file.py + - s3_file.txt: + file: s3://bucket_name/key + - gcs_file.txt: + file: gs://bucket_name/key + - src/main.py: + content: | + print("Hello, World!") +folders: + - .devops/modules/mod1: + struct: terraform/module + - .devops/modules/mod2: + struct: terraform/module + with: + module_name: mymod2 + - ./: + struct: + - docker-files + - project/go +variables: + - project_name: + description: "The name of the project" + default: "MyProject" + type: string + - author_name: + description: "The name of the author" + type: string + default: "John Doe" +``` + +## Template variables + +Template variables are enclosed in `{{@` and `@}}` and are replaced at runtime. If a variable does not have a default value you will be prompted interactively. + +### Default variables + +- `file_name` – name of the file being processed. +- `file_directory` – directory of the file being processed. + +### Custom Jinja2 filters + +`struct` ships a few helper filters. + +- **latest_release** – fetch the latest GitHub release. +- **slugify** – convert a string into a slug. +- **default_branch** – return the default branch of a GitHub repository. + +```yaml +files: + - README.md: + content: | + Latest release: {{@ "httpdss/struct" | latest_release @}} +``` + +If a filter fails, a placeholder value is inserted. + +### `with` clause + +Nested structures can receive extra variables using the `with` clause. These values are merged with the global variables. + +```yaml +folders: + - .devops/modules/mod2: + struct: terraform/module + with: + module_name: mymod2 +``` diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 0000000..e755a3d --- /dev/null +++ b/docs/development.md @@ -0,0 +1,16 @@ +# Development + +1. Clone the repository. +2. Create a virtual environment and activate it: + +```sh +python3 -m venv .venv +source .venv/bin/activate +``` + +3. Install dependencies: + +```sh +pip install -r requirements.txt +pip install -r requirements.dev.txt +``` diff --git a/docs/github_trigger_script.md b/docs/github_trigger_script.md new file mode 100644 index 0000000..9899c93 --- /dev/null +++ b/docs/github_trigger_script.md @@ -0,0 +1,30 @@ +# GitHub Trigger Script + +The `github-trigger.py` utility triggers the `run-struct` workflow for every private repository in a GitHub organisation that matches certain criteria. + +## Features + +- Filter repositories by topic (for example `struct-enabled`). +- Check for the presence of a `.struct.yaml` file in the default branch. +- Ensure the `run-struct` workflow file exists. +- Dispatch the workflow for eligible repositories. + +## Usage + +Set a personal access token as `GITHUB_TOKEN` and run: + +```sh +python3 scripts/github-trigger.py +``` + +### Arguments + +- `` – GitHub organization name. +- `` – repository topic to search for. + +### Example + +```sh +export GITHUB_TOKEN=your_personal_access_token +python3 scripts/github-trigger.py my-org struct-enabled +``` diff --git a/docs/hooks.md b/docs/hooks.md new file mode 100644 index 0000000..6041e4c --- /dev/null +++ b/docs/hooks.md @@ -0,0 +1,24 @@ +# Pre-Generation and Post-Generation Hooks + +You can run shell commands before and after structure generation using `pre_hooks` and `post_hooks` in your configuration. + +- **pre_hooks** – commands executed before generation. If any command returns a non-zero exit code the process stops. +- **post_hooks** – commands executed after generation completes. If any command fails an error is shown. + +Example: + +```yaml +pre_hooks: + - echo "Preparing environment..." + - ./scripts/prep.sh + +post_hooks: + - echo "Generation complete!" + - ./scripts/cleanup.sh +files: + - README.md: + content: | + # My Project +``` + +Output from hooks is shown in the terminal. diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 0000000..cf8cdf6 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,55 @@ +# Installation + +## Using pip + +You can install STRUCT using pip: + +```sh +pip install git+https://github.com/httpdss/struct.git +``` + +## From Source + +Alternatively, clone the repository and install it locally: + +```sh +git clone https://github.com/httpdss/struct.git +cd struct +pip install -r requirements.txt +``` + +## Using Docker + +The Docker image lets you run the script without installing anything locally. See the [Quick Start](#quick-start) below for an example. + +## Quick Start + +### Generate a project from a local YAML file + +```sh +docker run \ + -v $(pwd):/workdir \ + -u $(id -u):$(id -g) \ + ghcr.io/httpdss/struct:main generate \ + /workdir/example/structure.yaml \ + /workdir/example_output +``` + +### Quick Start Using Docker Alpine + +For testing you can start a minimal Alpine container and install STRUCT inside it: + +```sh +docker run -it --entrypoint="" python:3.10-alpine sh -l +``` + +Inside the container install the tool and run it: + +```sh +apk add python-pip git vim +pip install git+https://github.com/httpdss/struct.git +mkdir example +cd example +cp /workdir/example/structure.yaml . +struct generate structure.yaml . +``` diff --git a/docs/usage.md b/docs/usage.md new file mode 100644 index 0000000..f08996b --- /dev/null +++ b/docs/usage.md @@ -0,0 +1,35 @@ +# Usage + +STRUCT exposes a command called `struct` with a set of subcommands: + +- `generate` – generate a project structure from a YAML file. +- `validate` – validate a configuration file. +- `info` – display information about the tool and its dependencies. +- `list` – list available structures shipped with the project. + +For help on any command run: + +```sh +struct -h +``` + +## Simple example + +```sh +struct generate terraform-module ./my-terraform-module +``` + +## More complete example + +```sh +struct generate \ + --log=DEBUG \ + --dry-run \ + --backup=/path/to/backup \ + --file-strategy=rename \ + --log-file=/path/to/logfile.log \ + terraform-module \ + ./my-terraform-module +``` + +The [configuration](configuration.md) file controls what files and folders are created. diff --git a/docs/yaml_schema.md b/docs/yaml_schema.md new file mode 100644 index 0000000..e1eb3be --- /dev/null +++ b/docs/yaml_schema.md @@ -0,0 +1,18 @@ +# YAML Schema + +A JSON schema is provided to help validate your configuration and provide autocompletion in supported editors. + +## Configuring VSCode + +1. Install the [YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml). +2. Add the following to your `.vscode/settings.json`: + +```json +{ + "yaml.schemas": { + "https://raw.githubusercontent.com/httpdss/struct/main/extras/schema.json": ".struct.yaml" + } +} +``` + +This associates the schema with all `.struct.yaml` files in the workspace.