{"id":45820722,"url":"https://github.com/deviantony/pctl","last_synced_at":"2026-02-26T20:07:13.379Z","repository":{"id":319279237,"uuid":"1078172912","full_name":"deviantony/pctl","owner":"deviantony","description":"A dev companion ! Deploy and re-deploy your app to Portainer using the CLI","archived":false,"fork":false,"pushed_at":"2025-11-22T11:06:08.000Z","size":5919,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-11-22T13:07:26.983Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deviantony.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-17T10:13:36.000Z","updated_at":"2025-11-11T20:08:16.000Z","dependencies_parsed_at":null,"dependency_job_id":"c4c6bb38-7766-4789-8513-239b454e44f9","html_url":"https://github.com/deviantony/pctl","commit_stats":null,"previous_names":["deviantony/pctl"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/deviantony/pctl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviantony%2Fpctl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviantony%2Fpctl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviantony%2Fpctl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviantony%2Fpctl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deviantony","download_url":"https://codeload.github.com/deviantony/pctl/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviantony%2Fpctl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29870621,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-26T18:42:30.764Z","status":"ssl_error","status_checked_at":"2026-02-26T18:41:47.936Z","response_time":89,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-02-26T20:07:12.832Z","updated_at":"2026-02-26T20:07:13.371Z","avatar_url":"https://github.com/deviantony.png","language":"Go","readme":"# pctl - Dev Companion for Portainer\n\nA simple CLI tool for quickly deploying and re-deploying your application on a Portainer environment. \n\n[![asciicast](https://asciinema.org/a/zYM6Tu31LesuRowrLDJZfGzcU.svg)](https://asciinema.org/a/zYM6Tu31LesuRowrLDJZfGzcU)\n\n## Usage\n\n### Prerequisites\n- A `docker-compose.yml` file in your project directory\n- Portainer instance with API access\n- Portainer API token (generate in Portainer: Settings \u003e API Keys)\n\n### 1. Initialize Configuration\n```bash\npctl init\n```\nInteractive setup to configure your Portainer connection (URL, API token, environment). This creates a `pctl.yml` configuration file.\n\n### 2. Deploy Your Application\n```bash\npctl deploy\n```\nDeploy your Docker Compose stack to Portainer. The tool reads your `docker-compose.yml` file and creates a new stack.\n\n**Build Support**: If your compose file contains `build:` directives, pctl will automatically build the images before deployment. See the [Build Configuration](#build-configuration) section for details.\n\n### 3. Update Existing Stack\n```bash\npctl redeploy\n```\nUpdate an existing stack with latest images.\n\n**Force Rebuild**: Use the `-f` or `--force-rebuild` flag to force rebuild images even if they haven't changed:\n```bash\npctl redeploy -f\n```\nThis sets `force_build=true` for this run, which includes no-cache behavior, ensuring a complete rebuild of all images.\n\n### 4. Check Status\n```bash\npctl ps\n```\nView stack status and running containers.\n\n### 5. View Logs\n```bash\npctl logs\n```\nStream real-time logs from your containers.\n\n**Log Options**:\n- `-t, --tail N`: Show the last N lines from the end of logs (default: 50)\n- `-s, --service NAME`: Show logs from a specific service only\n- `--non-interactive`: Force non-interactive mode (useful for testing and automation)\n\nExamples:\n```bash\n# Show last 100 lines from all containers\npctl logs -t 100\n\n# Show logs from a specific service\npctl logs -s web\n\n# Show last 20 lines from the database service\npctl logs -s database -t 20\n\n# Force non-interactive mode (useful for testing)\npctl logs --non-interactive\n\n# Non-interactive mode with specific service and tail count\npctl logs -s web -t 10 --non-interactive\n```\n\n### 6. Check Version\n```bash\npctl version\n```\nDisplay version information including version number, git commit hash, build timestamp, Go version, and target platform.\n\n## Configuration\n\npctl uses a `pctl.yml` configuration file created during initialization:\n\n```yaml\nportainer_url: https://portainer.example.com\napi_token: ptr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\nenvironment_id: 1\nstack_name: pctl_myproject\ncompose_file: docker-compose.yml\nskip_tls_verify: true\n```\n\nThe configuration includes:\n- **portainer_url**: Your Portainer instance URL\n- **api_token**: Portainer API token (starts with `ptr_`)\n- **environment_id**: Portainer environment ID\n- **stack_name**: Name for your stack in Portainer\n- **compose_file**: Path to your Docker Compose file\n- **skip_tls_verify**: Skip TLS verification for self-hosted instances\n\n## Build Configuration\n\nWhen using `build:` directives in your compose file, pctl can automatically build images before deployment. Add a `build` section to your `pctl.yml`:\n\n```yaml\nbuild:\n  mode: remote-build        # remote-build (default) or load\n  parallel: auto            # concurrent builds (auto or number)\n  tag_format: \"pctl-{{stack}}-{{service}}:{{hash}}\"\n  platforms: [\"linux/amd64\"]  # for load mode\n  extra_build_args: {}      # global build args\n  force_build: false        # force rebuild even if unchanged\n  warn_threshold_mb: 50     # warn if context \u003e 50MB\n```\n\n### Build Modes\n\n- **remote-build** (default): Builds images on the remote Docker engine via Portainer's Docker proxy. Most bandwidth-efficient.\n- **load**: Builds images locally and uploads them to the remote engine. Useful when the remote has poor internet access.\n\n### Example Compose with Build\n\n```yaml\nversion: '3.8'\nservices:\n  web:\n    build:\n      context: ./web\n      dockerfile: Dockerfile\n      args:\n        NODE_ENV: production\n    ports:\n      - \"3000:3000\"\n  \n  api:\n    build: ./api\n    ports:\n      - \"8080:8080\"\n```\n\nWhen you run `pctl deploy`, it will:\n1. Detect the `build:` directives\n2. Build the images according to your build configuration\n3. Transform the compose file to use the built images\n4. Deploy the stack to Portainer\n\n## Installation\n\nDownload the latest release for your platform from [GitHub Releases](https://github.com/deviantony/pctl/releases/latest):\n\n### Linux AMD64\n```bash\nwget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_linux_amd64.tar.gz\ntar -xzf pctl_1.2.2_linux_amd64.tar.gz\nchmod +x pctl\nsudo mv pctl /usr/local/bin/\n```\n\n### Linux ARM64\n```bash\nwget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_linux_arm64.tar.gz\ntar -xzf pctl_1.2.2_linux_arm64.tar.gz\nchmod +x pctl\nsudo mv pctl /usr/local/bin/\n```\n\n### macOS AMD64\n```bash\nwget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_darwin_amd64.tar.gz\ntar -xzf pctl_1.2.2_darwin_amd64.tar.gz\nchmod +x pctl\nsudo mv pctl /usr/local/bin/\n```\n\n### macOS ARM64 (Apple Silicon)\n```bash\nwget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_darwin_arm64.tar.gz\ntar -xzf pctl_1.2.2_darwin_arm64.tar.gz\nchmod +x pctl\nsudo mv pctl /usr/local/bin/\n```\n\n### Windows AMD64\n```bash\nwget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_windows_amd64.zip\n# Extract the zip file and move pctl.exe to your PATH\n```\n\n## Testing\n\npctl includes both unit tests and integration tests to ensure reliability and correctness.\n\n### Unit Tests\n\nRun the unit test suite:\n\n```bash\n# Run all unit tests\nmake test\n\n# Run tests with coverage report\nmake test-coverage\n```\n\nUnit tests cover:\n- Configuration loading and validation\n- Compose file parsing and transformation\n- Build system components (tagging, context handling, orchestration)\n- Portainer API client functionality\n- Error handling and formatting\n\n### Integration Tests\n\nIntegration tests run against a real Portainer instance to validate end-to-end functionality.\n\n**Prerequisites:**\n- Access to a Portainer instance\n- Portainer API token\n- Valid environment ID in Portainer\n\n**Setup:**\n\n1. Copy the example configuration:\n```bash\ncp integration_test_config.json.example integration_test_config.json\n```\n\n2. Edit `integration_test_config.json` with your Portainer details:\n```json\n{\n  \"portainer_url\": \"https://your-portainer-instance.com\",\n  \"api_token\": \"ptr_your_api_token_here\",\n  \"environment_id\": 1\n}\n```\n\n**Running Integration Tests:**\n\n```bash\n# Run integration tests\nmake test-integration\n```\n\nIntegration tests cover:\n- Deploying simple stacks (images only)\n- Redeploying existing stacks\n- Force rebuild with `-f` flag\n- Stack status checking (`pctl ps`)\n- Container logs (`pctl logs`)\n- Build functionality (both remote-build and load modes)\n- Error handling for non-existent stacks\n\n**Note:** Integration tests will create and clean up test stacks automatically. The tests use unique stack names to avoid conflicts.\n\n## Development\n\n### Creating Releases\n\nReleases are automated using [GoReleaser](https://goreleaser.com/) and GitHub Actions. To create a new release:\n\n```bash\n# Create a new release (e.g., version 1.1.1)\n./scripts/release.sh 1.1.1\n\n# Dry run to see what would happen\n./scripts/release.sh 1.1.1 --dry-run\n```\n\nThis will:\n1. Create a git tag `v1.1.1`\n2. Push the tag to GitHub\n3. GoReleaser automatically builds binaries for all platforms\n4. Creates a GitHub release with all binaries, checksums, and release notes\n\nSee [RELEASE.md](RELEASE.md) for detailed release process documentation.\n\n## Limitations\n\n- **Docker Standalone environments only** - Full support for Kubernetes environments is planned for future versions.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeviantony%2Fpctl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeviantony%2Fpctl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeviantony%2Fpctl/lists"}