https://github.com/sxwebdev/gcx
gcx is a lightweight CLI tool for cross-compiling Go binaries, publishing them, and deploying with custom commands. It uses a YAML config and Git tags for versioning, integrates with CI/CD pipelines, and sends notifications via popular messaging platforms.
https://github.com/sxwebdev/gcx
deployment devops golang self-hosted
Last synced: 3 months ago
JSON representation
gcx is a lightweight CLI tool for cross-compiling Go binaries, publishing them, and deploying with custom commands. It uses a YAML config and Git tags for versioning, integrates with CI/CD pipelines, and sends notifications via popular messaging platforms.
- Host: GitHub
- URL: https://github.com/sxwebdev/gcx
- Owner: sxwebdev
- Created: 2025-03-01T21:15:24.000Z (about 1 year ago)
- Default Branch: master
- Last Pushed: 2025-08-22T08:20:24.000Z (8 months ago)
- Last Synced: 2025-08-22T10:28:43.731Z (8 months ago)
- Topics: deployment, devops, golang, self-hosted
- Language: Go
- Homepage:
- Size: 55.7 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# gcx
**gcx** is a lightweight CLI tool for cross-compiling Go binaries and publishing them to cloud storage (e.g., S3). It reads build and release settings from a YAML configuration file (similar to GoReleaser), manages secrets via environment variables or a `.env` file, and automatically uses the current Git tag as the version.
## Features
- 🔨 **Cross-compilation:** Build Go binaries for multiple OS/architecture combinations.
- 🚀 **Automated publishing:** Upload build artifacts to S3 (including self-hosted endpoints) or SSH.
- ⚙️ **Configuration driven:** Use a YAML config file (`gcx.yaml`) to define build, archive, and publish settings.
- 🏷️ **Versioning:** Automatically determine the version using the current Git tag.
- 🔄 **CI/CD friendly:** Easily integrate with CI pipelines (e.g., GitLab CI).
- 🎣 **Hooks system:** Execute commands before and after build process.
- 📦 **Archiving:** Create archives (tar.gz) of your binaries with customizable naming.
- 🚢 **Deployment:** Deploy your artifacts to servers via SSH with custom commands.
- 🔔 **Notifications:** Send deployment status alerts to multiple channels (Telegram, Slack, Discord, Teams) using Shoutrrr.
## Installation
You can download the pre-built binary from the [releases](https://github.com/sxwebdev/gcx/releases) page or build it from source:
### Install from source
```bash
go install github.com/sxwebdev/gcx/cmd/gcx@latest
```
### Install via script
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/sxwebdev/gcx/refs/heads/master/scripts/install.sh)"
```
### Build from source
```bash
git clone https://github.com/sxwebdev/gcx.git
cd gcx
make build
```
### Use Docker Hub
```bash
docker pull sxwebdev/gcx:latest
```
## How to use
```text
# gcx help
NAME:
gcx - A tool for cross-compiling and publishing Go binaries
USAGE:
gcx [global options] [command [command options]]
COMMANDS:
build Compiles binaries
publish Publishes artifacts based on the configuration
deploy Deploys artifacts based on the configuration
release Release related commands
git Git related commands
version Displays the current version
config Configuration related commands
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--help, -h show help
```
### Git related commands
```text
NAME:
gcx git - Git related commands
USAGE:
gcx git [command [command options]]
COMMANDS:
version Displays the current git tag version
OPTIONS:
--help, -h show help
```
## Configuration
Create a YAML configuration file named `gcx.yaml` in your project root. An example configuration:
```yaml
version: 1
out_dir: dist
# Pre-build hooks
before:
hooks:
- go mod tidy
# Post-build hooks
after:
hooks:
- echo "Build completed!"
- ./scripts/notify-telegram.sh "New build ready!"
# Build configuration
builds:
- main: ./cmd/myapp
output_name: myapp
disable_platform_suffix: false
env:
- CGO_ENABLED=0
goos:
- linux
- darwin
goarch:
- amd64
- arm64
flags:
- -trimpath
ldflags:
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.Commit}}
- -X main.buildDate={{.Date}}
# Archive configuration
archives:
- formats: ["tar.gz"]
name_template: "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
# Artifact publishing configuration
blobs:
- provider: s3
name: s3-storage
bucket: your-bucket-name
directory: "releases/{{.Version}}"
region: us-west-1
endpoint: https://s3.example.com
- provider: ssh
name: stage-server
server: "stage.example.com"
user: "deployer"
key_path: "~/.ssh/deploy_key"
insecure_ignore_host_key: false
directory: "/var/www/releases/{{.Version}}"
# Deployment configuration
deploys:
- name: "production"
provider: "ssh"
server: "prod.example.com"
user: "deployer"
key_path: "~/.ssh/deploy_key"
insecure_ignore_host_key: false
commands:
- systemctl stop myapp
- cp /var/www/releases/myapp/latest/myapp /usr/local/bin/
- chmod +x /usr/local/bin/myapp
- systemctl start myapp
alerts:
urls:
- "telegram://token@telegram?channels=channel-1"
- "slack://token-a/token-b/token-c"
- "discord://token@channel"
- "teams://token-a/token-b/token-c"
- name: "staging"
provider: "ssh"
server: "staging.example.com"
user: "deployer"
key_path: "~/.ssh/deploy_key"
insecure_ignore_host_key: true
commands:
- docker-compose -f /opt/myapp/docker-compose.yml down
- cp /var/www/releases/myapp/latest/myapp /opt/myapp/
- docker-compose -f /opt/myapp/docker-compose.yml up -d
alerts:
urls:
- "telegram://token@telegram?channels=staging-alerts"
- "slack://token-a/token-b/token-c"
```
### Template Variables
The following variables are available in templates:
- `{{.Version}}` - Current version (from git tag)
- `{{.Commit}}` - Current git commit hash
- `{{.Date}}` - Build date
- `{{.Binary}}` - Binary name
- `{{.Os}}` - Operating system
- `{{.Arch}}` - Architecture
- `{{.Env.VARIABLE_NAME}}` - Environment variable value (from .env file or system environment)
### Environment Variables
You can use environment variables in your ldflags and other templates. Variables can be set in:
1. `.env` file in your project root
2. System environment variables
3. CI/CD environment variables
For security reasons, only environment variables that are explicitly referenced in your configuration (using `{{.Env.VARIABLE_NAME}}`) will be available during the build process. This prevents accidentally exposing sensitive system environment variables.
Example usage in ldflags:
```yaml
ldflags:
- "-X main.apiKey={{.Env.API_KEY}}"
- "-X main.environment={{.Env.ENVIRONMENT}}"
- "-X main.debug={{.Env.DEBUG}}"
```
And in your `.env` file:
```env
API_KEY=your-secret-key
ENVIRONMENT=production
DEBUG=false
```
You can also set build-specific environment variables in the configuration:
```yaml
builds:
- main: "./cmd/app"
env:
- "CGO_ENABLED=0"
- "GO111MODULE=on"
```
## Alerts Configuration
The tool supports sending deployment status notifications using [shoutrrr](https://containrrr.dev/shoutrrr/). You can configure alerts for each deployment to notify different channels about success or failure of the deployment.
### Supported Services
- Telegram
- Slack
- Discord
- Microsoft Teams
- And many more (see [shoutrrr services](https://containrrr.dev/shoutrrr/services/overview/))
### URL Formats
Here are examples of URL formats for different services:
```yaml
alerts:
urls:
# Telegram
- "telegram://token@telegram?channels=channel-1,channel-2"
# Slack
- "slack://token-a/token-b/token-c"
# Discord
- "discord://token@channel"
# Microsoft Teams
- "teams://token-a/token-b/token-c"
# Generic Webhook
- "generic://example.com/webhook?token=token"
```
### Alert Message Format
The alert message includes:
- Application name (from deploy configuration)
- Version (current Git tag)
- Deployment status (Success/Failed)
- Error details (in case of failure)
Example success message:
```text
Deployment Status Update
Application: myapp-production
Version: v1.2.3
Status: Success
```
Example failure message:
```text
Deployment Status Update
Application: myapp-production
Version: v1.2.3
Status: Failed
Error: command 'systemctl start myapp' failed: exit status 1
```
## CLI Usage
Once installed, you can run the following commands:
```bash
# Initialize a new gcx.yaml configuration file
gcx config init
gcx config init --os linux --arch amd64 # Create config for specific platform
gcx config init --main ./cmd/myapp # Create config with custom main file
gcx config init --config custom.yaml # Create config with custom name
gcx config init --force # Overwrite existing config
# Build binaries according to configuration
gcx build
# Publish artifacts to configured destinations
gcx publish
# Deploy artifacts using configured deployment settings
gcx deploy
gcx deploy --name production # Deploy specific configuration
# Show current git tag version
gcx git version
# Generate a changelog between current and previous git tags
gcx release changelog
gcx release changelog --stable # Compare with previous stable version
# Show gcx version information
gcx version
```
The changelog command generates a markdown-formatted list of changes between the current and previous git tags, including:
- List of changes with commit messages
- Author of each change
- Short commit hash
- Full changelog comparison URL
Example changelog output:
```markdown
## What's Changed
- Add new feature by @author in abc1234
- Fix documentation by @another-author in def5678
**Full Changelog**: https://github.com/user/repo/compare/v0.0.1...v0.0.2
```
### Configuration Initialization
The `config init` command creates a new `gcx.yaml` file with default settings. Available flags:
- `--os, -o`: Target operating system (default: current OS)
- `--arch, -a`: Target architecture (default: current arch)
- `--main, -m`: Path to the main Go file (default: ./cmd/app)
- `--config, -c`: Path to the configuration file (default: gcx.yaml)
- `--force, -f`: Force overwrite existing config file
Example of generated configuration:
```yaml
version: 1
out_dir: dist
builds:
- main: ./cmd/app
output_name: myapp
disable_platform_suffix: false
goos:
- linux
goarch:
- amd64
flags:
- -trimpath
ldflags:
- -s -w
- -X main.version={{.Version}}
- -X main.commit={{.Commit}}
- -X main.buildDate={{.Date}}
```
## GitLab CI/CD Integration Example
```yaml
image: sxwebdev/gcx:latest
stages:
- build
- publish
- deploy
variables:
GCX_CONFIG: gcx.yaml
build:
stage: build
script:
- gcx build --config $GCX_CONFIG
artifacts:
paths:
- dist/
publish:
stage: publish
script:
- gcx publish --config $GCX_CONFIG
only:
- tags
deploy:
stage: deploy
script:
- gcx deploy --config $GCX_CONFIG --name production
only:
- tags
when: manual
```
In this pipeline:
- The `build` stage compiles binaries, creates archives, and stores them in `dist/`
- The `publish` stage uploads artifacts to configured destinations
- The `deploy` stage (manual trigger) deploys the application to production
- Ensure all necessary environment variables are set in your GitLab CI/CD settings
## License
Distributed under the MIT License. See `LICENSE` for more information.