https://github.com/deviantony/pctl
A dev companion ! Deploy and re-deploy your app to Portainer using the CLI
https://github.com/deviantony/pctl
Last synced: about 2 months ago
JSON representation
A dev companion ! Deploy and re-deploy your app to Portainer using the CLI
- Host: GitHub
- URL: https://github.com/deviantony/pctl
- Owner: deviantony
- License: mit
- Created: 2025-10-17T10:13:36.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-11-22T11:06:08.000Z (5 months ago)
- Last Synced: 2025-11-22T13:07:26.983Z (5 months ago)
- Language: Go
- Size: 5.64 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# pctl - Dev Companion for Portainer
A simple CLI tool for quickly deploying and re-deploying your application on a Portainer environment.
[](https://asciinema.org/a/zYM6Tu31LesuRowrLDJZfGzcU)
## Usage
### Prerequisites
- A `docker-compose.yml` file in your project directory
- Portainer instance with API access
- Portainer API token (generate in Portainer: Settings > API Keys)
### 1. Initialize Configuration
```bash
pctl init
```
Interactive setup to configure your Portainer connection (URL, API token, environment). This creates a `pctl.yml` configuration file.
### 2. Deploy Your Application
```bash
pctl deploy
```
Deploy your Docker Compose stack to Portainer. The tool reads your `docker-compose.yml` file and creates a new stack.
**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.
### 3. Update Existing Stack
```bash
pctl redeploy
```
Update an existing stack with latest images.
**Force Rebuild**: Use the `-f` or `--force-rebuild` flag to force rebuild images even if they haven't changed:
```bash
pctl redeploy -f
```
This sets `force_build=true` for this run, which includes no-cache behavior, ensuring a complete rebuild of all images.
### 4. Check Status
```bash
pctl ps
```
View stack status and running containers.
### 5. View Logs
```bash
pctl logs
```
Stream real-time logs from your containers.
**Log Options**:
- `-t, --tail N`: Show the last N lines from the end of logs (default: 50)
- `-s, --service NAME`: Show logs from a specific service only
- `--non-interactive`: Force non-interactive mode (useful for testing and automation)
Examples:
```bash
# Show last 100 lines from all containers
pctl logs -t 100
# Show logs from a specific service
pctl logs -s web
# Show last 20 lines from the database service
pctl logs -s database -t 20
# Force non-interactive mode (useful for testing)
pctl logs --non-interactive
# Non-interactive mode with specific service and tail count
pctl logs -s web -t 10 --non-interactive
```
### 6. Check Version
```bash
pctl version
```
Display version information including version number, git commit hash, build timestamp, Go version, and target platform.
## Configuration
pctl uses a `pctl.yml` configuration file created during initialization:
```yaml
portainer_url: https://portainer.example.com
api_token: ptr_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
environment_id: 1
stack_name: pctl_myproject
compose_file: docker-compose.yml
skip_tls_verify: true
```
The configuration includes:
- **portainer_url**: Your Portainer instance URL
- **api_token**: Portainer API token (starts with `ptr_`)
- **environment_id**: Portainer environment ID
- **stack_name**: Name for your stack in Portainer
- **compose_file**: Path to your Docker Compose file
- **skip_tls_verify**: Skip TLS verification for self-hosted instances
## Build Configuration
When using `build:` directives in your compose file, pctl can automatically build images before deployment. Add a `build` section to your `pctl.yml`:
```yaml
build:
mode: remote-build # remote-build (default) or load
parallel: auto # concurrent builds (auto or number)
tag_format: "pctl-{{stack}}-{{service}}:{{hash}}"
platforms: ["linux/amd64"] # for load mode
extra_build_args: {} # global build args
force_build: false # force rebuild even if unchanged
warn_threshold_mb: 50 # warn if context > 50MB
```
### Build Modes
- **remote-build** (default): Builds images on the remote Docker engine via Portainer's Docker proxy. Most bandwidth-efficient.
- **load**: Builds images locally and uploads them to the remote engine. Useful when the remote has poor internet access.
### Example Compose with Build
```yaml
version: '3.8'
services:
web:
build:
context: ./web
dockerfile: Dockerfile
args:
NODE_ENV: production
ports:
- "3000:3000"
api:
build: ./api
ports:
- "8080:8080"
```
When you run `pctl deploy`, it will:
1. Detect the `build:` directives
2. Build the images according to your build configuration
3. Transform the compose file to use the built images
4. Deploy the stack to Portainer
## Installation
Download the latest release for your platform from [GitHub Releases](https://github.com/deviantony/pctl/releases/latest):
### Linux AMD64
```bash
wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_linux_amd64.tar.gz
tar -xzf pctl_1.2.2_linux_amd64.tar.gz
chmod +x pctl
sudo mv pctl /usr/local/bin/
```
### Linux ARM64
```bash
wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_linux_arm64.tar.gz
tar -xzf pctl_1.2.2_linux_arm64.tar.gz
chmod +x pctl
sudo mv pctl /usr/local/bin/
```
### macOS AMD64
```bash
wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_darwin_amd64.tar.gz
tar -xzf pctl_1.2.2_darwin_amd64.tar.gz
chmod +x pctl
sudo mv pctl /usr/local/bin/
```
### macOS ARM64 (Apple Silicon)
```bash
wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_darwin_arm64.tar.gz
tar -xzf pctl_1.2.2_darwin_arm64.tar.gz
chmod +x pctl
sudo mv pctl /usr/local/bin/
```
### Windows AMD64
```bash
wget https://github.com/deviantony/pctl/releases/latest/download/pctl_1.2.2_windows_amd64.zip
# Extract the zip file and move pctl.exe to your PATH
```
## Testing
pctl includes both unit tests and integration tests to ensure reliability and correctness.
### Unit Tests
Run the unit test suite:
```bash
# Run all unit tests
make test
# Run tests with coverage report
make test-coverage
```
Unit tests cover:
- Configuration loading and validation
- Compose file parsing and transformation
- Build system components (tagging, context handling, orchestration)
- Portainer API client functionality
- Error handling and formatting
### Integration Tests
Integration tests run against a real Portainer instance to validate end-to-end functionality.
**Prerequisites:**
- Access to a Portainer instance
- Portainer API token
- Valid environment ID in Portainer
**Setup:**
1. Copy the example configuration:
```bash
cp integration_test_config.json.example integration_test_config.json
```
2. Edit `integration_test_config.json` with your Portainer details:
```json
{
"portainer_url": "https://your-portainer-instance.com",
"api_token": "ptr_your_api_token_here",
"environment_id": 1
}
```
**Running Integration Tests:**
```bash
# Run integration tests
make test-integration
```
Integration tests cover:
- Deploying simple stacks (images only)
- Redeploying existing stacks
- Force rebuild with `-f` flag
- Stack status checking (`pctl ps`)
- Container logs (`pctl logs`)
- Build functionality (both remote-build and load modes)
- Error handling for non-existent stacks
**Note:** Integration tests will create and clean up test stacks automatically. The tests use unique stack names to avoid conflicts.
## Development
### Creating Releases
Releases are automated using [GoReleaser](https://goreleaser.com/) and GitHub Actions. To create a new release:
```bash
# Create a new release (e.g., version 1.1.1)
./scripts/release.sh 1.1.1
# Dry run to see what would happen
./scripts/release.sh 1.1.1 --dry-run
```
This will:
1. Create a git tag `v1.1.1`
2. Push the tag to GitHub
3. GoReleaser automatically builds binaries for all platforms
4. Creates a GitHub release with all binaries, checksums, and release notes
See [RELEASE.md](RELEASE.md) for detailed release process documentation.
## Limitations
- **Docker Standalone environments only** - Full support for Kubernetes environments is planned for future versions.