### Devpush Installation Script (Ubuntu/Debian) Source: https://context7.com/hunvreus/devpush/llms.txt Installs Devpush on a fresh Ubuntu/Debian server using a curl command. Supports options for specifying the repository URL, reference, and controlling telemetry and verbosity. ```bash # Install on a fresh Ubuntu/Debian server curl -fsSL https://install.devpu.sh | sudo bash # Options: --repo --ref --yes --no-telemetry --verbose ``` -------------------------------- ### Create New Project Configuration Source: https://context7.com/hunvreus/devpush/llms.txt Guides the creation of a new project within /dev/push, linking it to a GitHub repository. This involves selecting a repository, configuring build settings, and defining environment variables. ```bash # Step 1: Select repository (HTMX partial) curl "https://your-domain.com/api/github/repo-select?account=myorg" \ -H "Cookie: auth_token=" # Step 2: Get repository list with search curl "https://your-domain.com/api/github/repo-list?account=myorg&query=myapp" \ -H "Cookie: auth_token=" # Step 3: Create project (POST form data) curl -X POST "https://your-domain.com/myteam/new-project/details" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "repo_id=12345" \ -d "name=my-app" \ -d "production_branch=main" \ -d "preset=nextjs" \ -d "runner=node-20" \ -d "build_command=npm install && npm run build" \ -d "start_command=npm start" \ -d "env_vars-0-key=DATABASE_URL" \ -d "env_vars-0-value=postgresql://..." \ -d "env_vars-0-environment=" # Project config stored in database: # { ``` -------------------------------- ### Start Command Input Field (HTML/Jinja) Source: https://github.com/hunvreus/devpush/blob/main/app/templates/project/macros/build-and-deploy.html Renders a text input for the start command, which is responsible for launching the application. The command must listen on `0.0.0.0:8000`. The field includes a label, Alpine.js reference, and usage instructions. ```html {# START COMMAND #} {{ form.start_command.label() }} {{ form.start_command( id=False, class="w-full font-mono text-[13px]", **{'x-ref': 'startCommandInput'} ) }} {% for error in form.start_command.errors %} {{ error }} {% endfor %} {{ _('Start the app (must listen on `0.0.0.0:8000`).') | safe }} ``` -------------------------------- ### Start DevPush Service Source: https://github.com/hunvreus/devpush/blob/main/README.md Starts the DevPush service using systemctl. This command assumes DevPush has been installed and configured, and it manages the service lifecycle. ```bash sudo systemctl start devpush.service ``` -------------------------------- ### Install DevPush Service Source: https://github.com/hunvreus/devpush/blob/main/README.md Installs the DevPush service on Ubuntu/Debian systems using a curl command. This script downloads and executes the installation process, setting up the necessary components for DevPush. ```bash curl -fsSL https://install.devpu.sh | sudo bash ``` -------------------------------- ### Clone DevPush Repository and Setup Development Environment Source: https://github.com/hunvreus/devpush/blob/main/README.md Clones the DevPush repository from GitHub and sets up the local development environment. It involves creating a data directory, copying example environment variables, and editing the .env file with GitHub App credentials. ```bash git clone https://github.com/hunvreus/devpush.git cd devpush mkdir -p data cp .env.dev.example data/.env # Edit data/.env with your GitHub App credentials ``` -------------------------------- ### Conventional Commits Example Source: https://github.com/hunvreus/devpush/blob/main/CONTRIBUTING.md Illustrates the conventional commits format for commit messages, including different types like 'feat', 'fix', 'docs', 'refactor', 'test', and 'chore', with example scopes. ```text feat(scripts): add upgrade hooks for version-specific migrations This commit introduces a new directory for upgrade hooks and implements the logic for executing them based on version comparisons. fix(install): use sudo for /var/lib/devpush operations Ensures that operations on /var/lib/devpush are performed with sudo, as it's owned by the root user. docs(contributing): add production scripts conventions Adds a section to the contributing guide detailing conventions for production scripts, including error handling and privilege management. ``` -------------------------------- ### Update Metadata Examples (JSON) Source: https://github.com/hunvreus/devpush/blob/main/scripts/upgrades/README.md Examples demonstrating the structure of update metadata JSON files. These files define defaults for update scopes, such as forcing a full stack update or specifying a set of components to update, along with a user-facing reason for the update. ```json { "full": true, "reason": "Postgres image upgrade requires full stack restart" } ``` ```json { "components": "app,worker-jobs,worker-monitor", "reason": "Only app and workers changed" } ``` -------------------------------- ### Start DevPush Development Stack Source: https://github.com/hunvreus/devpush/blob/main/README.md Starts the DevPush Docker Compose stack for development. This script manages the lifecycle of the development environment, including services and hot reloading. ```bash ./scripts/start.sh ``` -------------------------------- ### Manage DevPush Docker Stack Source: https://github.com/hunvreus/devpush/blob/main/README.md Provides commands to manage the DevPush Docker stack, including starting, stopping, and restarting services. These scripts are essential for operating DevPush in a development or self-hosted environment. ```bash ./scripts/start.sh ./scripts/stop.sh ./scripts/restart.sh ``` -------------------------------- ### GitHub Webhook Handler Source: https://context7.com/hunvreus/devpush/llms.txt Processes incoming webhook events from GitHub to automate deployments and manage repository-related actions. It verifies signatures and handles events like code pushes, app installations, and repository changes. ```bash # GitHub sends webhook to this endpoint # Signature verification via X-Hub-Signature-256 header curl -X POST https://your-domain.com/api/github/webhook \ -H "Content-Type: application/json" \ -H "X-GitHub-Event: push" \ -H "X-Hub-Signature-256: sha256=" \ -d '{ "ref": "refs/heads/main", "after": "abc123def456...", "repository": {"id": 12345, "full_name": "owner/repo"}, "pusher": {"name": "username"}, "head_commit": { "message": "Fix bug in authentication", "timestamp": "2024-01-15T10:30:00Z" } }' # Supported events: # - push: Triggers deployment for matching projects # - installation: App installed/uninstalled/suspended # - installation_repositories: Repos added/removed from installation # - repository: Repository deleted/renamed/transferred ``` -------------------------------- ### Devpush Stack Management Scripts Source: https://context7.com/hunvreus/devpush/llms.txt Scripts for managing the Devpush service stack, including starting, stopping, restarting, and checking status. Options are available for skipping database migrations, setting timeouts, and performing hard stops. ```bash # Start/stop/restart the stack sudo /opt/devpush/scripts/start.sh # --no-migrate --timeout --verbose sudo /opt/devpush/scripts/stop.sh # --hard sudo /opt/devpush/scripts/restart.sh # --no-migrate # Check stack status sudo /opt/devpush/scripts/status.sh ``` -------------------------------- ### Pre-Deploy Command Input Field (HTML/Jinja) Source: https://github.com/hunvreus/devpush/blob/main/app/templates/project/macros/build-and-deploy.html Generates a text input for pre-deployment commands. These commands are executed before the application starts, often used for tasks like database migrations. It includes a label, Alpine.js reference, and explanatory text. ```html {# PRE-DEPLOY COMMAND #} {{ form.pre_deploy_command.label() }} {{ form.pre_deploy_command( id=False, class="w-full font-mono text-[13px]", **{'x-ref': 'preDeployCommandInput'} ) }} {% for error in form.pre_deploy_command.errors %} {{ error }} {% endfor %} {{ _('Run commands before we start the app (e.g. migrate database).') }} ``` -------------------------------- ### Build Command Input Field (HTML/Jinja) Source: https://github.com/hunvreus/devpush/blob/main/app/templates/project/macros/build-and-deploy.html Renders a text input for the build command. This field is intended for commands that install dependencies and build the project. It includes a label, Alpine.js reference, and descriptive text. ```html {# BUILD COMMAND #} {{ form.build_command.label() }} {{ form.build_command( id=False, class="w-full font-mono text-[13px]", **{'x-ref': 'buildCommandInput'} ) }} {% for error in form.build_command.errors %} {{ error }} {% endfor %} {{ _('Install dependencies and build the project.') }} ``` -------------------------------- ### Project Settings - Environments API Source: https://context7.com/hunvreus/devpush/llms.txt Create and manage deployment environments with branch mapping for your projects. ```APIDOC ## POST /myteam/projects/{project_id}/settings?fragment=environment ### Description Creates or updates a deployment environment for a project. ### Method POST ### Endpoint `/myteam/projects/{project_id}/settings?fragment=environment` ### Parameters #### Query Parameters - **fragment** (string) - Required - Must be `environment`. #### Request Body - **name** (string) - Required - The name of the environment. - **slug** (string) - Required (for creation) - A unique identifier for the environment. - **color** (string) - Optional - A color associated with the environment. - **branch** (string) - Required - The branch or branch pattern(s) for the environment (e.g., `develop`, `main`, `feature/*`). Multiple branches can be comma-separated. - **environment_id** (string) - Required (for update) - The ID of the environment to update. - **csrf_token** (string) - Required - CSRF token for authentication. ### Request Example ```json { "name": "Staging", "slug": "staging", "color": "yellow", "branch": "develop", "csrf_token": "" } ``` ### Response #### Success Response (200) - **message** (string) - Confirmation message. #### Response Example ```json { "message": "Environment created successfully." } ``` ``` -------------------------------- ### Create New Project Source: https://context7.com/hunvreus/devpush/llms.txt Allows users to create a new project linked to a GitHub repository, configuring build settings and environment variables. ```APIDOC ## API Endpoints for Project Creation ### Description This section outlines the API endpoints involved in creating a new project within the /dev/push platform. It includes steps for selecting a repository, listing available repositories, and finally creating the project with its configuration. ### Method GET (for repo-select and repo-list), POST (for details) ### Endpoints 1. **/api/github/repo-select** 2. **/api/github/repo-list** 3. **/myteam/new-project/details** ### Parameters #### Authentication - **Cookie**: `auth_token=` - Required for all project creation steps. #### 1. GET /api/github/repo-select - **Query Parameters** - **account** (string) - Required - The GitHub account or organization name. #### 2. GET /api/github/repo-list - **Query Parameters** - **account** (string) - Required - The GitHub account or organization name. - **query** (string) - Optional - A search query to filter repositories. #### 3. POST /myteam/new-project/details - **Path Parameters** - **myteam** (string) - The team slug. - **new-project** (string) - The project name. - **Request Body (form data)** - **repo_id** (integer) - Required - The ID of the GitHub repository. - **name** (string) - Required - The name of the project. - **production_branch** (string) - Required - The main branch for production deployments (e.g., `main`). - **preset** (string) - Optional - A deployment preset (e.g., `nextjs`). - **runner** (string) - Optional - The Docker runner image to use (e.g., `node-20`). - **build_command** (string) - Optional - The command to build the application. - **start_command** (string) - Optional - The command to start the application. - **env_vars-[index]-key** (string) - Optional - Key for an environment variable. - **env_vars-[index]-value** (string) - Optional - Value for an environment variable. - **env_vars-[index]-environment** (string) - Optional - Environment scope for the variable (e.g., `production`, `preview`). ### Request Examples **Step 1: Select repository (example using HTMX partial)** ```bash curl "https://your-domain.com/api/github/repo-select?account=myorg" \ -H "Cookie: auth_token=" ``` **Step 2: Get repository list with search** ```bash curl "https://your-domain.com/api/github/repo-list?account=myorg&query=myapp" \ -H "Cookie: auth_token=" ``` **Step 3: Create project** ```bash curl -X POST "https://your-domain.com/myteam/new-project/details" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "repo_id=12345" \ -d "name=my-app" \ -d "production_branch=main" \ -d "preset=nextjs" \ -d "runner=node-20" \ -d "build_command=npm install && npm run build" \ -d "start_command=npm start" \ -d "env_vars-0-key=DATABASE_URL" \ -d "env_vars-0-value=postgresql://..." \ -d "env_vars-0-environment=" ``` ### Response #### Success Response (200 or 201) - The response typically indicates the successful creation of the project and may include project details or a redirect URL. #### Project Configuration Storage - Project configuration, including environment variables, is stored in the platform's database. ``` -------------------------------- ### Trigger Manual Deployment via API Source: https://context7.com/hunvreus/devpush/llms.txt Initiates a deployment for a specified commit and environment using a curl command. Requires authentication token and project details. The response is a redirect to the deployment page. ```bash # Get available commits for an environment curl "https://your-domain.com/myteam/projects/my-app/deploy?environment_id=prod" \ -H "Cookie: auth_token=" # Create deployment (POST form data) curl -X POST "https://your-domain.com/myteam/projects/my-app/deploy" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "commit=main:abc123def456789..." # Response: Redirect to deployment page # /myteam/projects/my-app/deployments/ ``` -------------------------------- ### Project Settings - Custom Domains Source: https://context7.com/hunvreus/devpush/llms.txt Add and verify custom domains for a project, with automatic SSL certificate provisioning. ```APIDOC ## Project Settings - Custom Domains ### Description Add and verify custom domains for a project, with automatic SSL certificate provisioning. ### Method POST ### Endpoint `/myteam/projects/my-app/settings?fragment=domain` ### Parameters #### Query Parameters - **fragment** (string) - Required - Set to `domain` to manage custom domains. #### Request Body - **hostname** (string) - Required - The custom domain name (e.g., `app.example.com`). - **type** (string) - Required - The type of domain mapping. Options: `route` (direct routing), `301` (permanent redirect), `302` (temporary redirect). - **environment_id** (string) - Required - The ID of the environment to associate the domain with. - **csrf_token** (string) - Required - CSRF token for authentication. ### Request Example (Add Domain) ```bash curl -X POST "https://your-domain.com/myteam/projects/my-app/settings?fragment=domain" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "hostname=app.example.com" \ -d "type=route" \ -d "environment_id=prod" \ -d "csrf_token=" ``` ### Endpoint `/myteam/projects/my-app/settings?fragment=verify_domain` ### Parameters #### Query Parameters - **fragment** (string) - Required - Set to `verify_domain` to verify a custom domain. #### Request Body - **domain_id** (string) - Required - The ID of the domain to verify. - **csrf_token** (string) - Required - CSRF token for authentication. ### Request Example (Verify Domain) ```bash curl -X POST "https://your-domain.com/myteam/projects/my-app/settings?fragment=verify_domain" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "domain_id=123" \ -d "csrf_token=" ``` ### Response #### Success Response Domain is added or verified. Ensure your DNS records are configured correctly: - **CNAME**: `app.example.com` -> `.deploy.example.com` - **OR A**: `app.example.com` -> `` ``` -------------------------------- ### Real-time Deployment Logs (SSE) Source: https://context7.com/hunvreus/devpush/llms.txt Stream real-time build and runtime logs for a deployment using Server-Sent Events (SSE). ```APIDOC ## Real-time Deployment Logs (SSE) ### Description Stream real-time build and runtime logs for a deployment using Server-Sent Events. ### Method GET ### Endpoint `//projects//deployments//events` ### Parameters #### Path Parameters - **team_id** (string) - Required - The ID of the team. - **project_id** (string) - Required - The ID of the project. - **deployment_id** (string) - Required - The ID of the deployment. #### Query Parameters - **start_timestamp** (integer) - Optional - Resume streaming from a specific nanosecond timestamp. ### Request Example ```bash # Connect to SSE endpoint for deployment logs curl -N "https://your-domain.com//projects//deployments//events" \ -H "Cookie: auth_token=" \ -H "Accept: text/event-stream" # Optional: Resume from specific timestamp curl -N "https://your-domain.com//projects//deployments//events?start_timestamp=1705312345000000000" \ -H "Cookie: auth_token=" ``` ### Response #### SSE Events - **event: deployment_log** - **id**: `` - **data**: `` - **event: deployment_concluded** - **id**: `` - **data**: `succeeded` | `failed` | `canceled` - **event: deployment_log_closed** - **id**: `` - **data**: `succeeded` | `failed` | `canceled` ``` -------------------------------- ### Manage Project Custom Domains via API Source: https://context7.com/hunvreus/devpush/llms.txt Adds and verifies custom domains for a project, enabling automatic SSL certificate provisioning. Supports different domain types like 'route', '301', and '302' redirects. DNS verification is also managed through this API. ```bash # Add a custom domain curl -X POST "https://your-domain.com/myteam/projects/my-app/settings?fragment=domain" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "hostname=app.example.com" \ -d "type=route" \ -d "environment_id=prod" \ -d "csrf_token=" # Domain types: # - route: Direct routing to deployment # - 301: Permanent redirect # - 302: Temporary redirect # Verify domain DNS configuration curl -X POST "https://your-domain.com/myteam/projects/my-app/settings?fragment=verify_domain" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "domain_id=123" \ -d "csrf_token=" # Required DNS records: # CNAME app.example.com -> .deploy.example.com # OR A app.example.com -> ``` -------------------------------- ### Calculate and Format Time Duration (Jinja Macro) Source: https://github.com/hunvreus/devpush/blob/main/app/templates/deployment/macros/duration.html This Jinja macro calculates the time difference between a start and end timestamp, formatting it into minutes and seconds. It also displays the start time in a human-readable 'time ago' format. Dependencies include the `timestamp()` and `time_ago` filters. ```jinja {% macro duration(started_at=None, concluded_at=None) %} {% if concluded_at %} {% set seconds = concluded_at.timestamp() - started_at.timestamp() %} {% set minutes = (seconds // 60)|int %} {% set remaining_seconds = (seconds % 60)|int %} {% if minutes > 0 %} {{ minutes }}m {{ remaining_seconds }}s {% else %} {{ remaining_seconds }}s {% endif %} ({{ started_at | time_ago }}) {% else %} {% endif %} {% endmacro %} ``` -------------------------------- ### Project Settings - Environment Variables Source: https://context7.com/hunvreus/devpush/llms.txt Manage encrypted environment variables for a project, optionally scoped to specific environments. ```APIDOC ## Project Settings - Environment Variables ### Description Manage encrypted environment variables for a project, optionally scoped to specific environments. ### Method POST ### Endpoint `/myteam/projects/my-app/settings?fragment=env_vars` ### Parameters #### Query Parameters - **fragment** (string) - Required - Set to `env_vars` to manage environment variables. #### Request Body - **env_vars-[index]-key** (string) - Required - The key of the environment variable. - **env_vars-[index]-value** (string) - Required - The value of the environment variable. Values are encrypted at rest. - **env_vars-[index]-environment** (string) - Optional - The environment to scope this variable to. If empty, it applies to all environments. - **csrf_token** (string) - Required - CSRF token for authentication. ### Request Example ```bash curl -X POST "https://your-domain.com/myteam/projects/my-app/settings?fragment=env_vars" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "env_vars-0-key=DATABASE_URL" \ -d "env_vars-0-value=postgresql://user:pass@host/db" \ -d "env_vars-0-environment=" \ -d "env_vars-1-key=API_KEY" \ -d "env_vars-1-value=secret123" \ -d "env_vars-1-environment=production" \ -d "csrf_token=" ``` ### Response #### Success Response Environment variables are updated. The structure of environment variables is as follows: ```json [ {"key": "DATABASE_URL", "value": "...", "environment": ""}, // All environments {"key": "API_KEY", "value": "...", "environment": "production"} // Production only ] ``` ``` -------------------------------- ### Admin Settings API Source: https://context7.com/hunvreus/devpush/llms.txt Access and manage system-wide administrative settings. ```APIDOC ## GET /admin/settings ### Description Retrieves system-wide administrative settings. Requires superadmin privileges (user_id=1). ### Method GET ### Endpoint `/admin/settings` ### Parameters #### Headers - **Cookie**: `auth_token=` ### Response #### Success Response (200) - **user_allowlist** (object) - Settings for user allowlisting. - **github_app_status** (object) - Status of GitHub App installation and configuration. - **registry_configuration** (object) - Configuration for registries. - **user_management** (object) - Information for managing all users. #### Response Example ```json { "user_allowlist": { "enabled": true, "patterns": ["*@example.com"] }, "github_app_status": { "installed": true, "webhook_configured": true }, "registry_configuration": { "runners_enabled": true }, "user_management": { "total_users": 100 } } ``` ``` -------------------------------- ### Authentication - GitHub OAuth Login Source: https://context7.com/hunvreus/devpush/llms.txt Initiates the authentication flow using GitHub OAuth. ```APIDOC ## GET /auth/github ### Description Initiates the GitHub OAuth 2.0 authentication flow. This endpoint redirects the user to GitHub to authorize the application. ### Method GET ### Endpoint /auth/github ### Parameters None ### Request Example ```bash curl -L https://your-domain.com/auth/github ``` ### Response #### Success Response (302 Redirect) - Redirects the user's browser to GitHub's authorization server. #### Callback Endpoint - **GET /auth/github/callback?code=** - After user authorization on GitHub, they are redirected back to this callback URL. - The `code` parameter is exchanged for an access token, and the user session is established. ``` -------------------------------- ### Bash Upgrade Hook Script Structure Source: https://github.com/hunvreus/devpush/blob/main/CONTRIBUTING.md Provides a template for bash upgrade hook scripts used in the /dev/push project. It includes standard header, an example idempotent operation, and the required exit code. ```bash #!/usr/bin/env bash set -Eeuo pipefail echo "Description of what this upgrade does..." # Idempotent operations only # Example: Ensure a directory is owned by root if [[ -d /var/lib/devpush ]]; then sudo chown -R root:root /var/lib/devpush 2>/dev/null || true fi exit 0 ``` -------------------------------- ### Project Logs Search API Source: https://context7.com/hunvreus/devpush/llms.txt Query and filter deployment logs with various search criteria. ```APIDOC ## GET /myteam/projects/{project_id}/logs?fragment=logs ### Description Searches and filters deployment logs for a project. ### Method GET ### Endpoint `/myteam/projects/{project_id}/logs?fragment=logs` ### Parameters #### Query Parameters - **fragment** (string) - Required - Must be `logs`. - **deployment_id** (string) - Optional - Filter logs for a specific deployment. - **environment_id** (string) - Optional - Filter logs by environment. - **branch** (string) - Optional - Filter logs by branch name. - **keyword** (string) - Optional - Perform full-text search in log messages. - **date_from** (string) - Optional - Start date for the time range (YYYY-MM-DD). - **time_from** (string) - Optional - Start time for the time range (HH:MM). - **date_to** (string) - Optional - End date for the time range (YYYY-MM-DD). - **time_to** (string) - Optional - End time for the time range (HH:MM). - **timezone_offset** (integer) - Optional - Client timezone offset in minutes. ### Request Example ```json { "deployment_id": "", "environment_id": "prod", "branch": "main", "keyword": "error", "date_from": "2024-01-01", "time_from": "00:00", "date_to": "2024-01-15", "time_to": "23:59" } ``` ### Response #### Success Response (200) - **logs** (array) - An array of log entries. - **timestamp** (string) - Timestamp of the log entry. - **message** (string) - The log message. #### Response Example ```json { "logs": [ { "timestamp": "2024-01-10T10:30:00Z", "message": "An error occurred during deployment." } ] } ``` ``` -------------------------------- ### Create Deployment Record and Emit Redis Event (Python) Source: https://context7.com/hunvreus/devpush/llms.txt Creates a new deployment record using the DeploymentService and emits a Redis stream event for real-time updates. It takes project details, commit information, database session, and a Redis client as input. The function returns the created deployment model instance. ```python from services.deployment import DeploymentService from models import Project, User from sqlalchemy.ext.asyncio import AsyncSession from redis.asyncio import Redis async def create_deployment( project: Project, branch: str, commit: dict, db: AsyncSession, redis_client: Redis, current_user: User | None = None, ): """ Create a new deployment for a project. Args: project: Project model instance branch: Git branch name (e.g., "main", "feature/auth") commit: GitHub commit data with sha, author, message db: Database session redis_client: Redis client for event streaming current_user: Optional user who triggered the deployment Returns: Deployment model instance """ deployment_service = DeploymentService() # Commit structure from GitHub API: commit = { "sha": "abc123def456789...", "author": {"login": "username"}, "commit": { "message": "Fix authentication bug", "author": {"date": "2024-01-15T10:30:00Z"} } } deployment = await deployment_service.create( project=project, branch=branch, commit=commit, db=db, redis_client=redis_client, trigger="user", # or "webhook" for GitHub push current_user=current_user, ) # Queue the deployment job job = await queue.enqueue_job("start_deployment", deployment.id) deployment.job_id = job.job_id await db.commit() return deployment ``` -------------------------------- ### Authentication - Google OAuth Login Source: https://context7.com/hunvreus/devpush/llms.txt Initiates the authentication flow using Google OAuth. ```APIDOC ## GET /auth/google ### Description Initiates the Google OAuth 2.0 authentication flow. This endpoint redirects the user to Google to authorize the application. ### Method GET ### Endpoint /auth/google ### Parameters None ### Request Example ```bash curl -L https://your-domain.com/auth/google ``` ### Response #### Success Response (302 Redirect) - Redirects the user's browser to Google's authorization server. #### Callback Endpoint - **GET /auth/google/callback?code=&state=** - After user authorization on Google, they are redirected back to this callback URL. - The `code` and `state` parameters are used to exchange for an access token and establish the user session. ``` -------------------------------- ### Get CSRF Token (Jinja2) Source: https://github.com/hunvreus/devpush/blob/main/app/templates/project/partials/_settings-build-and-deploy.html Retrieves a CSRF token for form security. The `id=False` argument indicates that a specific token ID is not required. This is a common practice in web frameworks to protect against cross-site request forgery attacks. ```jinja2 {{ build_and_deploy_form.csrf_token(id=False) }} ``` -------------------------------- ### Bash Scripting: Output Formatting and Logging Source: https://github.com/hunvreus/devpush/blob/main/AGENTS.md Defines conventions for outputting messages and logging within bash scripts. It promotes the use of `run_cmd` for structured output, `printf` for formatted messages, and specific color codes for success messages. ```bash printf '\n' printf "${GRN}…${NC}\n" printf "%s Building runner images...\n" "$CHILD_MARK" run_cmd "${CHILD_MARK} Starting services..." "${COMPOSE_BASE[@]}" up -d ``` -------------------------------- ### Display and Copy Storage ID Source: https://github.com/hunvreus/devpush/blob/main/app/templates/team/partials/_storage-settings-general.html This snippet shows how to display a storage ID and provide a button to copy it. It uses a Jinja macro 'copy' for the copy functionality, making it easy for users to get the storage ID. The button is styled to be an icon and is positioned absolutely. ```html {{ storage.id }} {{ copy( value=storage.id, class="btn-icon-ghost text-muted-foreground hover:text-accent-foreground absolute right-1.5 top-1/2 -translate-y-1/2 size-6" ) }} ``` -------------------------------- ### Render Email Form Fields with Jinja Source: https://github.com/hunvreus/devpush/blob/main/app/templates/user/partials/_settings-email.html This snippet shows how to render various parts of an email form using Jinja templating. It includes CSRF token, internationalized labels, an email input field with error handling, and action buttons. It relies on a form object (email_form) and internationalization functions (_). ```jinja {{ email_form.csrf_token() }} {{ _("Email") }} ----------------- {{ _("The email address used for authentication and notifications.") }} {{ email_form.email.label(class="label") }} {{ email_form.email(class="input w-full") }} {% for error in email_form.email.errors %} {{ error }} {% endfor %} {{ _('Cancel') }} {{ _('Save') }} {% include "icons/loader.svg" %} {{ _('Saving') }} ``` -------------------------------- ### Storage Management API Source: https://context7.com/hunvreus/devpush/llms.txt Create and manage persistent storage resources like databases and volumes. ```APIDOC ## POST /myteam/storage ### Description Creates a new storage resource (database or volume). ### Method POST ### Endpoint `/myteam/storage` ### Parameters #### Request Body - **name** (string) - Required - The name of the storage resource. - **type** (string) - Required - The type of storage (`database` or `volume`). - **csrf_token** (string) - Required - CSRF token for authentication. ### Request Example ```json { "name": "myapp-db", "type": "database", "csrf_token": "" } ``` ## POST /myteam/projects/{project_id}/storage?fragment=connect_storage ### Description Connects a storage resource to a project for specific environments. ### Method POST ### Endpoint `/myteam/projects/{project_id}/storage?fragment=connect_storage` ### Parameters #### Query Parameters - **fragment** (string) - Required - Must be `connect_storage`. #### Request Body - **storage_id** (string) - Required - The ID of the storage resource to connect. - **environment_ids** (string) - Required - A comma-separated list of environment IDs to connect the storage to (e.g., `prod,staging`). - **csrf_token** (string) - Required - CSRF token for authentication. ### Request Example ```json { "storage_id": "", "environment_ids": "prod,staging", "csrf_token": "" } ``` ``` -------------------------------- ### Manual Deployment Source: https://context7.com/hunvreus/devpush/llms.txt Trigger a manual deployment for a specific commit and environment. You can also retrieve available commits for an environment. ```APIDOC ## Manual Deployment ### Description Trigger a deployment for a specific commit and environment. ### Method GET ### Endpoint `/myteam/projects/my-app/deploy?environment_id=prod` ### Query Parameters - **environment_id** (string) - Required - The ID of the environment to get available commits for. ### Method POST ### Endpoint `/myteam/projects/my-app/deploy` ### Parameters #### Query Parameters - **environment_id** (string) - Required - The ID of the environment to deploy to. #### Request Body - **commit** (string) - Required - The commit hash or branch name to deploy. ### Request Example ```bash # Get available commits for an environment curl "https://your-domain.com/myteam/projects/my-app/deploy?environment_id=prod" \ -H "Cookie: auth_token=" # Create deployment (POST form data) curl -X POST "https://your-domain.com/myteam/projects/my-app/deploy" \ -H "Cookie: auth_token=" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "commit=main:abc123def456789..." ``` ### Response #### Success Response (302 Redirect) Redirects to the deployment page: `/myteam/projects/my-app/deployments/` ``` -------------------------------- ### Bash Scripting: Running Commands as Service User Source: https://github.com/hunvreus/devpush/blob/main/AGENTS.md Details how to execute commands with the correct file ownership for the service user. This is crucial for tasks like creating directories or files within the application's data or application directories. ```bash runuser -u "$user" -- bash -c '…' ``` -------------------------------- ### Bash Scripting: File and Directory Creation Source: https://github.com/hunvreus/devpush/blob/main/AGENTS.md Provides a safe way to create files and directories, ensuring that the operation is idempotent. It checks for the existence of the target before attempting creation. ```bash [[ ! -f … ]] install -d … ``` -------------------------------- ### Render Build and Deploy Form (Jinja2) Source: https://github.com/hunvreus/devpush/blob/main/app/templates/project/partials/_settings-build-and-deploy.html Renders the build and deploy form using a Jinja2 macro. It takes the form object, presets, runners, and initialization values as input. This macro is responsible for displaying the configuration options for building and deploying the project. ```jinja2 {% from "project/macros/build-and-deploy.html" import render_build_and_deploy with context %} {{ render_build_and_deploy(build_and_deploy_form, presets, runners, init_values=false) }} ``` -------------------------------- ### Generate DNS Record Instructions (Jinja2) Source: https://github.com/hunvreus/devpush/blob/main/app/templates/project/partials/_settings-domains.html This Jinja2 template snippet dynamically generates instructions for adding DNS records. It determines whether to recommend ANAME/ALIAS or CNAME records based on the 'is_apex' flag and constructs the necessary record name and value, including the environment ID hostname. It also provides fallback instructions for providers not supporting ANAME/ALIAS. ```jinja2 {% else %} {% set env_id_hostname = project.slug + '-env-id-' + domain.environment_id + '.' + deploy_domain %} {% if domain.is_apex %} {{ _('Add a `ANAME` or `ALIAS` record at your domain provider:') | safe }} {% else %} {{ _('Add a `CNAME` record at your domain provider:') | safe }} {% endif %} {{ _("Type") }} {{ _("Name") }} {{ _("Value") }} {% if domain.is_apex %} `ANAME` or `ALIAS` {% else %} `CNAME` {% endif %} `{{ "@" if domain.is_apex else domain.hostname.split(".")[0] }}` {{ env_id_hostname }} {{ copy( value=env_id_hostname, class="btn-icon-ghost text-muted-foreground hover:text-accent-foreground" ) }} {% if domain.is_apex %} {{ _('If your DNS provider does not support ANAME or ALIAS records, use an A record pointing to `%(server_ip)s`', server_ip=server_ip) | safe }} {% endif %} {{ _('After changing the records, click "Verify" to check status.') }} {{ verify_domain_form.csrf_token(id=False) }} {{ verify_domain_form.domain_id( id=False, value=domain.id ) }} {{ _('Verify') }} {% include "icons/loader.svg" %} {% endif %} {% endif %} {% endfor %} {{ render_domain_form(index=0) }} {% include "icons/plus.svg" %} {{ _('Add domain') }} {% include "icons/loader.svg" %} {{ _('Saving') }} ``` -------------------------------- ### Jinja2 Partial Includes for Project Settings Sections Source: https://github.com/hunvreus/devpush/blob/main/app/templates/project/pages/settings.html Demonstrates the use of Jinja2's 'include' directive to embed content from separate partial files. Each include corresponds to a distinct section of the project settings page, promoting modularity. ```jinja2 {# GENERAL #} {% include "project/partials/_settings-general.html" %} {# ENVIRONMENTS #} {% include "project/partials/_settings-environments.html" %} {# ENVIRONMENT VARIABLES #} {% include "project/partials/_settings-env-vars.html" %} {# DOMAINS #} {% include "project/partials/_settings-domains.html" %} {# BUILD & DEPLOY #} {% include "project/partials/_settings-build-and-deploy.html" %} {# DANGER ZONE #} {% include "project/partials/_settings-danger.html" %} ``` -------------------------------- ### Bash Version Comparison with sort -V Source: https://github.com/hunvreus/devpush/blob/main/CONTRIBUTING.md Demonstrates using `sort -V` for semantic version comparison in shell scripts. It covers handling standard versions and prerelease versions, noting the difference from strict semver for prereleases. ```bash VERSIONS=("1.0.0" "0.1.0" "0.1.0-alpha" "0.1.1" "0.1.0-beta.1" "0.1.0-rc.2") # Sort versions semantically echo "Sorted versions:" printf "%s\n" "${VERSIONS[@]}" | sort -V # Example comparison CURRENT_VERSION="0.1.0" HOOK_VERSION="0.1.1" TARGET_VERSION="1.0.0" if [[ "$(printf '%s\n' "$CURRENT_VERSION" "$HOOK_VERSION" | sort -V | head -n 1)" != "$HOOK_VERSION" ]] && [[ "$(printf '%s\n' "$HOOK_VERSION" "$TARGET_VERSION" | sort -V | head -n 1)" == "$HOOK_VERSION" ]]; then echo "Hook version $HOOK_VERSION should be applied." fi ``` -------------------------------- ### Bash Scripting: Environment Detection and Path Management Source: https://github.com/hunvreus/devpush/blob/main/AGENTS.md Ensures scripts correctly detect their environment and derive paths from established variables. It emphasizes sourcing shared libraries and avoiding hardcoded paths, relying instead on environment variables like APP_DIR and DATA_DIR. ```bash SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/lib.sh" ``` -------------------------------- ### Query Deployment Logs from Loki (Python) Source: https://context7.com/hunvreus/devpush/llms.txt Queries deployment logs from Loki with support for filtering by project, deployment, environment, branch, and keywords. It also supports pagination and timestamp-based filtering. The function can also be used to push log entries to Loki. ```python from services.loki import LokiService async def query_logs(): loki = LokiService(loki_url="http://loki:3100") # Get deployment logs with filters logs = await loki.get_logs( project_id="abc123...", deployment_id="def456...", # Optional environment_id="prod", # Optional branch="main", # Optional keyword="error", # Optional - case-insensitive search limit=100, # Max entries to return start_timestamp="1705312345000000000", # Nanoseconds end_timestamp="1705398745000000000", timeout=10.0, ) # Log entry structure: # { # "timestamp_iso": "2024-01-15T10:30:45.123Z", # "timestamp": "1705312245123456789", # Nanoseconds # "message": "Server started on port 8000", # "level": "info", # Parsed from structured log # "labels": { # "project_id": "abc123...", # "deployment_id": "def456...", # "environment_id": "prod", # "branch": "main" # } # } # Push a log entry (used by deployment worker) await loki.push_log( labels={ "project_id": "abc123...", "deployment_id": "def456...", "environment_id": "prod", "branch": "main", "stream": "stdout", }, line="Application started successfully", ) ``` -------------------------------- ### Render Build and Deploy Macro (Jinja/HTML) Source: https://github.com/hunvreus/devpush/blob/main/app/templates/project/macros/build-and-deploy.html The 'render_build_and_deploy' macro generates HTML form elements for build and deployment configurations. It processes presets and runners, dynamically enabling/disabling options based on selected presets and runner tags. It also initializes form values and handles user interactions via Alpine.js. ```html {% macro render_build_and_deploy(form, presets, runners, init_values=true) %} var presets = {{ presets | tojson }}; var runners = {{ runners | tojson }}; presets = presets.map(preset => { const presetTags = Array.isArray(preset?.tags) ? preset.tags : []; if (!presetTags.length) return { ...preset, allowedRunners: null }; const matched = runners.filter(runner => Array.isArray(runner?.tags) && presetTags.every(tag => runner.tags.includes(tag))); return { ...preset, allowedRunners: matched.length ? matched.map(r => r.slug) : null }; }); Alpine.data('devpushBuild', () => ({ selectedPreset: '{{ form.preset.data or '' }}', presets: presets, runners: runners, init() { this.setPreset(this.selectedPreset, false, {{ init_values | lower }}); }, getPreset() { return this.presets.find(p => p.slug === this.selectedPreset); }, disableRunnerOptions(preset) { if (!$refs.runnerInput) return; $refs.runnerInput.querySelectorAll('option').forEach(option => { if (preset?.allowedRunners) { option.disabled = !preset.allowedRunners.includes(option.value); } else if (!preset?.category) { option.disabled = false; } else { if (option.parentElement.tagName === 'OPTGROUP' && option.parentElement.label === preset?.category) { option.disabled = false; } else { option.disabled = true; } } }); }, setPreset(slug = null, force = false, apply = true) { this.selectedPreset = slug || ''; if (!slug) { this.disableRunnerOptions(null); return; } const preset = this.getPreset(); if (!preset) return; const applyValue = (ref, value) => { if (!ref) return; if (value === undefined || value === null) return; if (force || !ref.value) ref.value = value; }; this.disableRunnerOptions(preset); if (!apply) return; let runnerValue = preset?.config?.runner; const options = Array.from($refs.runnerInput.querySelectorAll('option')); if (!options.find(option => option.value === runnerValue && !option.disabled)) { runnerValue = options.find(option => !option.disabled && option.parentElement?.label === preset?.category)?.value; } applyValue($refs.runnerInput, runnerValue); applyValue($refs.rootDirectoryInput, preset?.config?.root_directory); applyValue($refs.buildCommandInput, preset?.config?.build_command); applyValue($refs.preDeployCommandInput, preset?.config?.pre_deploy_command); applyValue($refs.startCommandInput, preset?.config?.start_command); } })) } {% endmacro %} ```