docs: rewrite CI/CD deployment guides with gordon push as recommended method
- deployment/index.md: decision matrix for 3 push methods, network topology guide, token scopes reference - deployment/github-actions.md: add gordon push workflow examples, fix checkout@v6 to v4, add docker-based alternative - deployment/gitlab-ci.md: new guide for GitLab CI/CD pipelines - deployment/generic-ci.md: new guide for Jenkins, CircleCI, Drone, and other CI systems - cli/push.md: update synopsis to [image], add auth/version auto-detection/CI sections - index.md: add GitLab CI and Generic CI navigation links
- commit
- a9c18869026b065d13eddd3ee0b65085fa14baa2
- author
- bnema · · 2026-03-18 21:48 UTC
- parent
- da431e6
- signature
- unsigned
6 files · +822 -183
M docs/cli/push.md +51 -12
| @@ -7,14 +7,14 @@ Tag, push, and optionally deploy an image to the Gordon registry. | |||
| 7 | 7 | ### Synopsis | |
| 8 | 8 | ||
| 9 | 9 | ```bash | |
| 10 | - | gordon push <domain> [options] | |
| 10 | + | gordon push [image] [options] | |
| 11 | 11 | ``` | |
| 12 | 12 | ||
| 13 | 13 | ### Arguments | |
| 14 | 14 | ||
| 15 | 15 | | Argument | Description | | |
| 16 | 16 | |----------|-------------| | |
| 17 | - | | `<domain>` | The route domain to resolve the registry and repository from | | |
| 17 | + | | `[image]` | Image name to push (optional). If omitted, auto-detected from Dockerfile labels or current directory name | | |
| 18 | 18 | ||
| 19 | 19 | ### Options | |
| 20 | 20 | ||
| @@ -27,14 +27,20 @@ gordon push <domain> [options] | |||
| 27 | 27 | | `--tag` | Override version tag (default: tag ref from CI, then `git describe --tags --dirty`) | | |
| 28 | 28 | | `--no-confirm` | Skip deploy confirmation prompt | | |
| 29 | 29 | | `--no-deploy` | Push only; skip deployment prompt | | |
| 30 | + | | `--domain` | Explicit domain override (legacy mode) | | |
| 30 | 31 | | `--remote` | Remote Gordon URL | | |
| 31 | 32 | | `--token` | Authentication token for remote | | |
| 32 | 33 | ||
| 33 | 34 | ### Description | |
| 34 | 35 | ||
| 35 | - | `gordon push` resolves the route image for `<domain>`, tags the image for the | |
| 36 | + | `gordon push` resolves the target image from the backend, tags it for the | |
| 36 | 37 | Gordon registry, pushes it, and optionally deploys it. | |
| 37 | 38 | ||
| 39 | + | Image resolution order: | |
| 40 | + | 1. If `--domain` is provided, uses domain-based route lookup | |
| 41 | + | 2. If an image name is provided as argument, resolves domain(s) from the backend | |
| 42 | + | 3. If no argument, auto-detects from Dockerfile `gordon.domain` label or current directory name | |
| 43 | + | ||
| 38 | 44 | To push attachment images (databases, caches, etc.), use `gordon attachments push`. | |
| 39 | 45 | ||
| 40 | 46 | - For first deploys, run `gordon bootstrap` first to create or update the route, attachments, and secrets, then run `gordon push` to upload and deploy the image. | |
| @@ -43,33 +49,64 @@ To push attachment images (databases, caches, etc.), use `gordon attachments pus | |||
| 43 | 49 | then falls back to `git describe --tags --dirty` (for example | |
| 44 | 50 | `v1.2.3-4-gabc1234` or `v1.2.3-dirty`). If no tag is found, `latest` is used. | |
| 45 | 51 | - When `--build` is set, the command builds with `docker buildx build --load` | |
| 46 | - | and injects `VERSION` into the build environment plus any `--build-arg` values. | |
| 52 | + | and injects `VERSION`, `GIT_TAG`, `GIT_SHA`, and `BUILD_TIME` into the build | |
| 53 | + | environment plus any `--build-arg` values. | |
| 47 | 54 | - Use `-f/--file` to build from a Dockerfile outside the current directory root. | |
| 48 | 55 | - The version tag and `latest` are both pushed (unless the version is `latest`). | |
| 49 | 56 | ||
| 57 | + | ### Authentication | |
| 58 | + | ||
| 59 | + | When used with `--remote`, gordon push authenticates in two ways: | |
| 60 | + | ||
| 61 | + | - **Admin API** (route resolution, deploy): uses `--token` or `$GORDON_TOKEN` as Bearer token | |
| 62 | + | - **Registry push**: automatically exchanges the token for a short-lived (5 min) registry access token via `/auth/token` -- no `docker login` required | |
| 63 | + | ||
| 64 | + | This means CI/CD pipelines only need a single secret (`GORDON_TOKEN`). | |
| 65 | + | ||
| 66 | + | ### Version Auto-Detection | |
| 67 | + | ||
| 68 | + | Gordon reads version tags from CI environment variables (in priority order): | |
| 69 | + | ||
| 70 | + | | CI System | Variable | Example | | |
| 71 | + | |-----------|----------|---------| | |
| 72 | + | | GitHub Actions | `$GITHUB_REF` | `refs/tags/v1.2.0` | | |
| 73 | + | | GitHub Actions | `$GITHUB_REF_TYPE` + `$GITHUB_REF_NAME` | `tag` + `v1.2.0` | | |
| 74 | + | | GitLab CI | `$CI_COMMIT_TAG` | `v1.2.0` | | |
| 75 | + | | Azure DevOps | `$BUILD_SOURCEBRANCH` | `refs/tags/v1.2.0` | | |
| 76 | + | | Any | `git describe --tags` | `v1.2.3-4-gabc1234` | | |
| 77 | + | | Fallback | - | `latest` | | |
| 78 | + | ||
| 50 | 79 | ### Examples | |
| 51 | 80 | ||
| 52 | 81 | ```bash | |
| 53 | - | # Build, push, and deploy | |
| 54 | - | gordon push myapp.example.com --build | |
| 82 | + | # Build, push, and deploy (auto-detect image name) | |
| 83 | + | gordon push --build --remote https://gordon.example.com --no-confirm | |
| 84 | + | ||
| 85 | + | # Specify image name explicitly | |
| 86 | + | gordon push myapp --build --remote https://gordon.example.com --no-confirm | |
| 55 | 87 | ||
| 56 | 88 | # Push existing local image, skip deploy | |
| 57 | - | gordon push myapp.example.com --tag v1.2.0 --no-deploy | |
| 89 | + | gordon push myapp --tag v1.2.0 --no-deploy | |
| 58 | 90 | ||
| 59 | 91 | # Push and deploy without confirmation | |
| 60 | - | gordon push myapp.example.com --no-confirm | |
| 92 | + | gordon push myapp --no-confirm | |
| 61 | 93 | ||
| 62 | 94 | # Build for ARM and pass build args | |
| 63 | - | gordon push myapp.example.com --build --platform linux/arm64 --build-arg CGO_ENABLED=0 | |
| 95 | + | gordon push myapp --build --platform linux/arm64 --build-arg CGO_ENABLED=0 | |
| 64 | 96 | ||
| 65 | 97 | # Build from a custom Dockerfile path | |
| 66 | - | gordon push myapp.example.com --build -f docker/app/Dockerfile | |
| 98 | + | gordon push myapp --build -f docker/app/Dockerfile | |
| 99 | + | ||
| 100 | + | # CI/CD usage (single env var, no docker login needed) | |
| 101 | + | export GORDON_TOKEN="your-token" | |
| 102 | + | gordon push --build --remote https://gordon.example.com --no-confirm | |
| 67 | 103 | ``` | |
| 68 | 104 | ||
| 69 | 105 | ### Notes | |
| 70 | 106 | ||
| 71 | 107 | - Remote mode required. See [CLI Overview](./index.md) for targeting options. | |
| 72 | - | - `gordon push` still requires the route to already exist so it can resolve the target image. | |
| 108 | + | - `gordon push` requires the route to already exist so it can resolve the target image. | |
| 109 | + | Use `gordon bootstrap` for first deploys. | |
| 73 | 110 | - `--build` requires Docker with Buildx. Docker Desktop includes it; on Linux, | |
| 74 | 111 | install the `docker-buildx-plugin` package. | |
| 75 | 112 | - Gordon uses native registry uploads instead of shelling out to `docker push`. | |
| @@ -81,6 +118,8 @@ gordon push myapp.example.com --build -f docker/app/Dockerfile | |||
| 81 | 118 | ## Related | |
| 82 | 119 | ||
| 83 | 120 | - [CLI Overview](./index.md) | |
| 121 | + | - [Deployment Overview](../deployment/index.md) | |
| 122 | + | - [GitHub Actions](../deployment/github-actions.md) | |
| 84 | 123 | - [Attachments Commands](./attachments.md) | |
| 85 | 124 | - [Routes Command](./routes.md) | |
| 86 | - | - [Serve Command](./serve.md) | |
| 125 | + | - [Authentication](../config/auth.md) | |
| @@ -7,14 +7,14 @@ Tag, push, and optionally deploy an image to the Gordon registry. | |||||
| 7 | ### Synopsis | 7 | ### Synopsis | ||
| 8 | 8 | ||||
| 9 | ```bash | 9 | ```bash | ||
| 10 | - | gordon push <domain> [options] | 10 | + | gordon push [image] [options] |
| 11 | ``` | 11 | ``` | ||
| 12 | 12 | ||||
| 13 | ### Arguments | 13 | ### Arguments | ||
| 14 | 14 | ||||
| 15 | | Argument | Description | | 15 | | Argument | Description | | ||
| 16 | |----------|-------------| | 16 | |----------|-------------| | ||
| 17 | - | | `<domain>` | The route domain to resolve the registry and repository from | | 17 | + | | `[image]` | Image name to push (optional). If omitted, auto-detected from Dockerfile labels or current directory name | |
| 18 | 18 | ||||
| 19 | ### Options | 19 | ### Options | ||
| 20 | 20 | ||||
| @@ -27,14 +27,20 @@ gordon push <domain> [options] | |||||
| 27 | | `--tag` | Override version tag (default: tag ref from CI, then `git describe --tags --dirty`) | | 27 | | `--tag` | Override version tag (default: tag ref from CI, then `git describe --tags --dirty`) | | ||
| 28 | | `--no-confirm` | Skip deploy confirmation prompt | | 28 | | `--no-confirm` | Skip deploy confirmation prompt | | ||
| 29 | | `--no-deploy` | Push only; skip deployment prompt | | 29 | | `--no-deploy` | Push only; skip deployment prompt | | ||
| 30 | + | | `--domain` | Explicit domain override (legacy mode) | | |||
| 30 | | `--remote` | Remote Gordon URL | | 31 | | `--remote` | Remote Gordon URL | | ||
| 31 | | `--token` | Authentication token for remote | | 32 | | `--token` | Authentication token for remote | | ||
| 32 | 33 | ||||
| 33 | ### Description | 34 | ### Description | ||
| 34 | 35 | ||||
| 35 | - | `gordon push` resolves the route image for `<domain>`, tags the image for the | 36 | + | `gordon push` resolves the target image from the backend, tags it for the |
| 36 | Gordon registry, pushes it, and optionally deploys it. | 37 | Gordon registry, pushes it, and optionally deploys it. | ||
| 37 | 38 | ||||
| 39 | + | Image resolution order: | |||
| 40 | + | 1. If `--domain` is provided, uses domain-based route lookup | |||
| 41 | + | 2. If an image name is provided as argument, resolves domain(s) from the backend | |||
| 42 | + | 3. If no argument, auto-detects from Dockerfile `gordon.domain` label or current directory name | |||
| 43 | + | ||||
| 38 | To push attachment images (databases, caches, etc.), use `gordon attachments push`. | 44 | To push attachment images (databases, caches, etc.), use `gordon attachments push`. | ||
| 39 | 45 | ||||
| 40 | - For first deploys, run `gordon bootstrap` first to create or update the route, attachments, and secrets, then run `gordon push` to upload and deploy the image. | 46 | - For first deploys, run `gordon bootstrap` first to create or update the route, attachments, and secrets, then run `gordon push` to upload and deploy the image. | ||
| @@ -43,33 +49,64 @@ To push attachment images (databases, caches, etc.), use `gordon attachments pus | |||||
| 43 | then falls back to `git describe --tags --dirty` (for example | 49 | then falls back to `git describe --tags --dirty` (for example | ||
| 44 | `v1.2.3-4-gabc1234` or `v1.2.3-dirty`). If no tag is found, `latest` is used. | 50 | `v1.2.3-4-gabc1234` or `v1.2.3-dirty`). If no tag is found, `latest` is used. | ||
| 45 | - When `--build` is set, the command builds with `docker buildx build --load` | 51 | - When `--build` is set, the command builds with `docker buildx build --load` | ||
| 46 | - | and injects `VERSION` into the build environment plus any `--build-arg` values. | 52 | + | and injects `VERSION`, `GIT_TAG`, `GIT_SHA`, and `BUILD_TIME` into the build |
| 53 | + | environment plus any `--build-arg` values. | |||
| 47 | - Use `-f/--file` to build from a Dockerfile outside the current directory root. | 54 | - Use `-f/--file` to build from a Dockerfile outside the current directory root. | ||
| 48 | - The version tag and `latest` are both pushed (unless the version is `latest`). | 55 | - The version tag and `latest` are both pushed (unless the version is `latest`). | ||
| 49 | 56 | ||||
| 57 | + | ### Authentication | |||
| 58 | + | ||||
| 59 | + | When used with `--remote`, gordon push authenticates in two ways: | |||
| 60 | + | ||||
| 61 | + | - **Admin API** (route resolution, deploy): uses `--token` or `$GORDON_TOKEN` as Bearer token | |||
| 62 | + | - **Registry push**: automatically exchanges the token for a short-lived (5 min) registry access token via `/auth/token` -- no `docker login` required | |||
| 63 | + | ||||
| 64 | + | This means CI/CD pipelines only need a single secret (`GORDON_TOKEN`). | |||
| 65 | + | ||||
| 66 | + | ### Version Auto-Detection | |||
| 67 | + | ||||
| 68 | + | Gordon reads version tags from CI environment variables (in priority order): | |||
| 69 | + | ||||
| 70 | + | | CI System | Variable | Example | | |||
| 71 | + | |-----------|----------|---------| | |||
| 72 | + | | GitHub Actions | `$GITHUB_REF` | `refs/tags/v1.2.0` | | |||
| 73 | + | | GitHub Actions | `$GITHUB_REF_TYPE` + `$GITHUB_REF_NAME` | `tag` + `v1.2.0` | | |||
| 74 | + | | GitLab CI | `$CI_COMMIT_TAG` | `v1.2.0` | | |||
| 75 | + | | Azure DevOps | `$BUILD_SOURCEBRANCH` | `refs/tags/v1.2.0` | | |||
| 76 | + | | Any | `git describe --tags` | `v1.2.3-4-gabc1234` | | |||
| 77 | + | | Fallback | - | `latest` | | |||
| 78 | + | ||||
| 50 | ### Examples | 79 | ### Examples | ||
| 51 | 80 | ||||
| 52 | ```bash | 81 | ```bash | ||
| 53 | - | # Build, push, and deploy | 82 | + | # Build, push, and deploy (auto-detect image name) |
| 54 | - | gordon push myapp.example.com --build | 83 | + | gordon push --build --remote https://gordon.example.com --no-confirm |
| 84 | + | ||||
| 85 | + | # Specify image name explicitly | |||
| 86 | + | gordon push myapp --build --remote https://gordon.example.com --no-confirm | |||
| 55 | 87 | ||||
| 56 | # Push existing local image, skip deploy | 88 | # Push existing local image, skip deploy | ||
| 57 | - | gordon push myapp.example.com --tag v1.2.0 --no-deploy | 89 | + | gordon push myapp --tag v1.2.0 --no-deploy |
| 58 | 90 | ||||
| 59 | # Push and deploy without confirmation | 91 | # Push and deploy without confirmation | ||
| 60 | - | gordon push myapp.example.com --no-confirm | 92 | + | gordon push myapp --no-confirm |
| 61 | 93 | ||||
| 62 | # Build for ARM and pass build args | 94 | # Build for ARM and pass build args | ||
| 63 | - | gordon push myapp.example.com --build --platform linux/arm64 --build-arg CGO_ENABLED=0 | 95 | + | gordon push myapp --build --platform linux/arm64 --build-arg CGO_ENABLED=0 |
| 64 | 96 | ||||
| 65 | # Build from a custom Dockerfile path | 97 | # Build from a custom Dockerfile path | ||
| 66 | - | gordon push myapp.example.com --build -f docker/app/Dockerfile | 98 | + | gordon push myapp --build -f docker/app/Dockerfile |
| 99 | + | ||||
| 100 | + | # CI/CD usage (single env var, no docker login needed) | |||
| 101 | + | export GORDON_TOKEN="your-token" | |||
| 102 | + | gordon push --build --remote https://gordon.example.com --no-confirm | |||
| 67 | ``` | 103 | ``` | ||
| 68 | 104 | ||||
| 69 | ### Notes | 105 | ### Notes | ||
| 70 | 106 | ||||
| 71 | - Remote mode required. See [CLI Overview](./index.md) for targeting options. | 107 | - Remote mode required. See [CLI Overview](./index.md) for targeting options. | ||
| 72 | - | - `gordon push` still requires the route to already exist so it can resolve the target image. | 108 | + | - `gordon push` requires the route to already exist so it can resolve the target image. |
| 109 | + | Use `gordon bootstrap` for first deploys. | |||
| 73 | - `--build` requires Docker with Buildx. Docker Desktop includes it; on Linux, | 110 | - `--build` requires Docker with Buildx. Docker Desktop includes it; on Linux, | ||
| 74 | install the `docker-buildx-plugin` package. | 111 | install the `docker-buildx-plugin` package. | ||
| 75 | - Gordon uses native registry uploads instead of shelling out to `docker push`. | 112 | - Gordon uses native registry uploads instead of shelling out to `docker push`. | ||
| @@ -81,6 +118,8 @@ gordon push myapp.example.com --build -f docker/app/Dockerfile | |||||
| 81 | ## Related | 118 | ## Related | ||
| 82 | 119 | ||||
| 83 | - [CLI Overview](./index.md) | 120 | - [CLI Overview](./index.md) | ||
| 121 | + | - [Deployment Overview](../deployment/index.md) | |||
| 122 | + | - [GitHub Actions](../deployment/github-actions.md) | |||
| 84 | - [Attachments Commands](./attachments.md) | 123 | - [Attachments Commands](./attachments.md) | ||
| 85 | - [Routes Command](./routes.md) | 124 | - [Routes Command](./routes.md) | ||
| 86 | - | - [Serve Command](./serve.md) | 125 | + | - [Authentication](../config/auth.md) |
A docs/deployment/generic-ci.md +204 -0
| @@ -0,0 +1,204 @@ | |||
| 1 | + | # Generic CI/CD Deployment | |
| 2 | + | ||
| 3 | + | Deploy with Gordon from any CI/CD system. | |
| 4 | + | ||
| 5 | + | ## Requirements | |
| 6 | + | ||
| 7 | + | - Docker available on CI runner (for building images) | |
| 8 | + | - Network access to your Gordon server (HTTPS) | |
| 9 | + | - Gordon binary (optional but recommended) | |
| 10 | + | ||
| 11 | + | ## Recommended: gordon push | |
| 12 | + | ||
| 13 | + | ### 1. Generate Deployment Token | |
| 14 | + | ||
| 15 | + | On your Gordon server: | |
| 16 | + | ||
| 17 | + | ```bash | |
| 18 | + | gordon auth token generate \ | |
| 19 | + | --subject ci-deploy \ | |
| 20 | + | --scopes "push,pull,admin:routes:read,admin:config:write" \ | |
| 21 | + | --expiry 0 | |
| 22 | + | ``` | |
| 23 | + | ||
| 24 | + | ### 2. Configure CI Secrets | |
| 25 | + | ||
| 26 | + | Add these secrets to your CI system: | |
| 27 | + | ||
| 28 | + | | Secret | Value | | |
| 29 | + | |--------|-------| | |
| 30 | + | | `GORDON_TOKEN` | The generated token | | |
| 31 | + | | `GORDON_REMOTE` | `https://gordon.example.com` | | |
| 32 | + | ||
| 33 | + | ### 3. Pipeline Steps | |
| 34 | + | ||
| 35 | + | ```bash | |
| 36 | + | # 1. Install Gordon binary | |
| 37 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 \ | |
| 38 | + | -o /usr/local/bin/gordon | |
| 39 | + | chmod +x /usr/local/bin/gordon | |
| 40 | + | ||
| 41 | + | # 2. Build, push, and deploy | |
| 42 | + | export GORDON_TOKEN="$GORDON_TOKEN" | |
| 43 | + | gordon push --build \ | |
| 44 | + | --remote "$GORDON_REMOTE" \ | |
| 45 | + | --no-confirm | |
| 46 | + | ``` | |
| 47 | + | ||
| 48 | + | Gordon auto-detects the version from CI environment variables: | |
| 49 | + | ||
| 50 | + | | CI System | Variable | Example | | |
| 51 | + | |-----------|----------|---------| | |
| 52 | + | | GitHub Actions | `$GITHUB_REF` | `refs/tags/v1.2.0` | | |
| 53 | + | | GitLab CI | `$CI_COMMIT_TAG` | `v1.2.0` | | |
| 54 | + | | Azure DevOps | `$BUILD_SOURCEBRANCH` | `refs/tags/v1.2.0` | | |
| 55 | + | | Other | `--tag` flag | `gordon push --tag v1.2.0` | | |
| 56 | + | ||
| 57 | + | ## Alternative: docker push | |
| 58 | + | ||
| 59 | + | If installing the Gordon binary is not possible: | |
| 60 | + | ||
| 61 | + | ```bash | |
| 62 | + | # 1. Login to Gordon registry | |
| 63 | + | echo "$GORDON_TOKEN" | docker login gordon.example.com \ | |
| 64 | + | -u ci-deploy --password-stdin | |
| 65 | + | ||
| 66 | + | # 2. Build and push | |
| 67 | + | docker build -t gordon.example.com/myapp:v1.0.0 . | |
| 68 | + | docker push gordon.example.com/myapp:v1.0.0 | |
| 69 | + | ``` | |
| 70 | + | ||
| 71 | + | This requires the token subject (`ci-deploy`) as the username. | |
| 72 | + | Gordon auto-deploys when it receives the image. | |
| 73 | + | ||
| 74 | + | ## CI System Examples | |
| 75 | + | ||
| 76 | + | ### Jenkins | |
| 77 | + | ||
| 78 | + | ```groovy | |
| 79 | + | pipeline { | |
| 80 | + | agent any | |
| 81 | + | environment { | |
| 82 | + | GORDON_TOKEN = credentials('gordon-token') | |
| 83 | + | GORDON_REMOTE = 'https://gordon.example.com' | |
| 84 | + | } | |
| 85 | + | stages { | |
| 86 | + | stage('Deploy') { | |
| 87 | + | steps { | |
| 88 | + | sh ''' | |
| 89 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 \ | |
| 90 | + | -o /usr/local/bin/gordon | |
| 91 | + | chmod +x /usr/local/bin/gordon | |
| 92 | + | gordon push --build --remote "$GORDON_REMOTE" --no-confirm | |
| 93 | + | ''' | |
| 94 | + | } | |
| 95 | + | } | |
| 96 | + | } | |
| 97 | + | } | |
| 98 | + | ``` | |
| 99 | + | ||
| 100 | + | ### CircleCI | |
| 101 | + | ||
| 102 | + | ```yaml | |
| 103 | + | version: 2.1 | |
| 104 | + | ||
| 105 | + | jobs: | |
| 106 | + | deploy: | |
| 107 | + | docker: | |
| 108 | + | - image: docker:24 | |
| 109 | + | steps: | |
| 110 | + | - checkout | |
| 111 | + | - setup_remote_docker | |
| 112 | + | - run: | |
| 113 | + | name: Install Gordon | |
| 114 | + | command: | | |
| 115 | + | apk add --no-cache curl | |
| 116 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 \ | |
| 117 | + | -o /usr/local/bin/gordon | |
| 118 | + | chmod +x /usr/local/bin/gordon | |
| 119 | + | - run: | |
| 120 | + | name: Deploy | |
| 121 | + | command: | | |
| 122 | + | gordon push --build \ | |
| 123 | + | --remote "$GORDON_REMOTE" \ | |
| 124 | + | --no-confirm | |
| 125 | + | ||
| 126 | + | workflows: | |
| 127 | + | deploy: | |
| 128 | + | jobs: | |
| 129 | + | - deploy: | |
| 130 | + | filters: | |
| 131 | + | tags: | |
| 132 | + | only: /^v.*/ | |
| 133 | + | branches: | |
| 134 | + | ignore: /.*/ | |
| 135 | + | ``` | |
| 136 | + | ||
| 137 | + | ### Drone | |
| 138 | + | ||
| 139 | + | ```yaml | |
| 140 | + | kind: pipeline | |
| 141 | + | type: docker | |
| 142 | + | name: deploy | |
| 143 | + | ||
| 144 | + | steps: | |
| 145 | + | - name: deploy | |
| 146 | + | image: docker:24 | |
| 147 | + | environment: | |
| 148 | + | GORDON_TOKEN: | |
| 149 | + | from_secret: gordon_token | |
| 150 | + | GORDON_REMOTE: | |
| 151 | + | from_secret: gordon_remote | |
| 152 | + | commands: | |
| 153 | + | - apk add --no-cache curl | |
| 154 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 | |
| 155 | + | -o /usr/local/bin/gordon | |
| 156 | + | - chmod +x /usr/local/bin/gordon | |
| 157 | + | - gordon push --build --remote "$GORDON_REMOTE" --no-confirm | |
| 158 | + | ||
| 159 | + | trigger: | |
| 160 | + | event: | |
| 161 | + | - tag | |
| 162 | + | ``` | |
| 163 | + | ||
| 164 | + | ## Token Scopes Reference | |
| 165 | + | ||
| 166 | + | | Workflow | Required Scopes | | |
| 167 | + | |----------|----------------| | |
| 168 | + | | Build + push + deploy | `push,pull,admin:routes:read,admin:config:write` | | |
| 169 | + | | Push only (no deploy) | `push,pull,admin:routes:read` | | |
| 170 | + | | docker push (auto-deploy) | `push,pull` | | |
| 171 | + | ||
| 172 | + | ## Troubleshooting | |
| 173 | + | ||
| 174 | + | ### "failed to verify token" | |
| 175 | + | ||
| 176 | + | The token is invalid or has been revoked. Generate a new one. | |
| 177 | + | ||
| 178 | + | ### "no route configured for image" | |
| 179 | + | ||
| 180 | + | The route must exist before pushing. Create it with: | |
| 181 | + | ||
| 182 | + | ```bash | |
| 183 | + | gordon routes add myapp.example.com myapp | |
| 184 | + | # or for first deploy: | |
| 185 | + | gordon bootstrap myapp.example.com myapp | |
| 186 | + | ``` | |
| 187 | + | ||
| 188 | + | ### Version shows "latest" | |
| 189 | + | ||
| 190 | + | Gordon could not detect a version tag. Either: | |
| 191 | + | - Tag your git repo: `git tag v1.0.0 && git push --tags` | |
| 192 | + | - Pass explicitly: `gordon push --tag v1.0.0` | |
| 193 | + | ||
| 194 | + | ### Large images time out | |
| 195 | + | ||
| 196 | + | Gordon uploads in 50MB chunks. For very large images (> 1GB), the push may take several minutes. Ensure your CI runner timeout is sufficient. | |
| 197 | + | ||
| 198 | + | ## Related | |
| 199 | + | ||
| 200 | + | - [GitHub Actions](./github-actions.md) | |
| 201 | + | - [GitLab CI](./gitlab-ci.md) | |
| 202 | + | - [Deployment Overview](./index.md) | |
| 203 | + | - [Authentication](../config/auth.md) | |
| 204 | + | - [Push Command](../cli/push.md) | |
| @@ -0,0 +1,204 @@ | |||||
| 1 | + | # Generic CI/CD Deployment | |||
| 2 | + | ||||
| 3 | + | Deploy with Gordon from any CI/CD system. | |||
| 4 | + | ||||
| 5 | + | ## Requirements | |||
| 6 | + | ||||
| 7 | + | - Docker available on CI runner (for building images) | |||
| 8 | + | - Network access to your Gordon server (HTTPS) | |||
| 9 | + | - Gordon binary (optional but recommended) | |||
| 10 | + | ||||
| 11 | + | ## Recommended: gordon push | |||
| 12 | + | ||||
| 13 | + | ### 1. Generate Deployment Token | |||
| 14 | + | ||||
| 15 | + | On your Gordon server: | |||
| 16 | + | ||||
| 17 | + | ```bash | |||
| 18 | + | gordon auth token generate \ | |||
| 19 | + | --subject ci-deploy \ | |||
| 20 | + | --scopes "push,pull,admin:routes:read,admin:config:write" \ | |||
| 21 | + | --expiry 0 | |||
| 22 | + | ``` | |||
| 23 | + | ||||
| 24 | + | ### 2. Configure CI Secrets | |||
| 25 | + | ||||
| 26 | + | Add these secrets to your CI system: | |||
| 27 | + | ||||
| 28 | + | | Secret | Value | | |||
| 29 | + | |--------|-------| | |||
| 30 | + | | `GORDON_TOKEN` | The generated token | | |||
| 31 | + | | `GORDON_REMOTE` | `https://gordon.example.com` | | |||
| 32 | + | ||||
| 33 | + | ### 3. Pipeline Steps | |||
| 34 | + | ||||
| 35 | + | ```bash | |||
| 36 | + | # 1. Install Gordon binary | |||
| 37 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 \ | |||
| 38 | + | -o /usr/local/bin/gordon | |||
| 39 | + | chmod +x /usr/local/bin/gordon | |||
| 40 | + | ||||
| 41 | + | # 2. Build, push, and deploy | |||
| 42 | + | export GORDON_TOKEN="$GORDON_TOKEN" | |||
| 43 | + | gordon push --build \ | |||
| 44 | + | --remote "$GORDON_REMOTE" \ | |||
| 45 | + | --no-confirm | |||
| 46 | + | ``` | |||
| 47 | + | ||||
| 48 | + | Gordon auto-detects the version from CI environment variables: | |||
| 49 | + | ||||
| 50 | + | | CI System | Variable | Example | | |||
| 51 | + | |-----------|----------|---------| | |||
| 52 | + | | GitHub Actions | `$GITHUB_REF` | `refs/tags/v1.2.0` | | |||
| 53 | + | | GitLab CI | `$CI_COMMIT_TAG` | `v1.2.0` | | |||
| 54 | + | | Azure DevOps | `$BUILD_SOURCEBRANCH` | `refs/tags/v1.2.0` | | |||
| 55 | + | | Other | `--tag` flag | `gordon push --tag v1.2.0` | | |||
| 56 | + | ||||
| 57 | + | ## Alternative: docker push | |||
| 58 | + | ||||
| 59 | + | If installing the Gordon binary is not possible: | |||
| 60 | + | ||||
| 61 | + | ```bash | |||
| 62 | + | # 1. Login to Gordon registry | |||
| 63 | + | echo "$GORDON_TOKEN" | docker login gordon.example.com \ | |||
| 64 | + | -u ci-deploy --password-stdin | |||
| 65 | + | ||||
| 66 | + | # 2. Build and push | |||
| 67 | + | docker build -t gordon.example.com/myapp:v1.0.0 . | |||
| 68 | + | docker push gordon.example.com/myapp:v1.0.0 | |||
| 69 | + | ``` | |||
| 70 | + | ||||
| 71 | + | This requires the token subject (`ci-deploy`) as the username. | |||
| 72 | + | Gordon auto-deploys when it receives the image. | |||
| 73 | + | ||||
| 74 | + | ## CI System Examples | |||
| 75 | + | ||||
| 76 | + | ### Jenkins | |||
| 77 | + | ||||
| 78 | + | ```groovy | |||
| 79 | + | pipeline { | |||
| 80 | + | agent any | |||
| 81 | + | environment { | |||
| 82 | + | GORDON_TOKEN = credentials('gordon-token') | |||
| 83 | + | GORDON_REMOTE = 'https://gordon.example.com' | |||
| 84 | + | } | |||
| 85 | + | stages { | |||
| 86 | + | stage('Deploy') { | |||
| 87 | + | steps { | |||
| 88 | + | sh ''' | |||
| 89 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 \ | |||
| 90 | + | -o /usr/local/bin/gordon | |||
| 91 | + | chmod +x /usr/local/bin/gordon | |||
| 92 | + | gordon push --build --remote "$GORDON_REMOTE" --no-confirm | |||
| 93 | + | ''' | |||
| 94 | + | } | |||
| 95 | + | } | |||
| 96 | + | } | |||
| 97 | + | } | |||
| 98 | + | ``` | |||
| 99 | + | ||||
| 100 | + | ### CircleCI | |||
| 101 | + | ||||
| 102 | + | ```yaml | |||
| 103 | + | version: 2.1 | |||
| 104 | + | ||||
| 105 | + | jobs: | |||
| 106 | + | deploy: | |||
| 107 | + | docker: | |||
| 108 | + | - image: docker:24 | |||
| 109 | + | steps: | |||
| 110 | + | - checkout | |||
| 111 | + | - setup_remote_docker | |||
| 112 | + | - run: | |||
| 113 | + | name: Install Gordon | |||
| 114 | + | command: | | |||
| 115 | + | apk add --no-cache curl | |||
| 116 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 \ | |||
| 117 | + | -o /usr/local/bin/gordon | |||
| 118 | + | chmod +x /usr/local/bin/gordon | |||
| 119 | + | - run: | |||
| 120 | + | name: Deploy | |||
| 121 | + | command: | | |||
| 122 | + | gordon push --build \ | |||
| 123 | + | --remote "$GORDON_REMOTE" \ | |||
| 124 | + | --no-confirm | |||
| 125 | + | ||||
| 126 | + | workflows: | |||
| 127 | + | deploy: | |||
| 128 | + | jobs: | |||
| 129 | + | - deploy: | |||
| 130 | + | filters: | |||
| 131 | + | tags: | |||
| 132 | + | only: /^v.*/ | |||
| 133 | + | branches: | |||
| 134 | + | ignore: /.*/ | |||
| 135 | + | ``` | |||
| 136 | + | ||||
| 137 | + | ### Drone | |||
| 138 | + | ||||
| 139 | + | ```yaml | |||
| 140 | + | kind: pipeline | |||
| 141 | + | type: docker | |||
| 142 | + | name: deploy | |||
| 143 | + | ||||
| 144 | + | steps: | |||
| 145 | + | - name: deploy | |||
| 146 | + | image: docker:24 | |||
| 147 | + | environment: | |||
| 148 | + | GORDON_TOKEN: | |||
| 149 | + | from_secret: gordon_token | |||
| 150 | + | GORDON_REMOTE: | |||
| 151 | + | from_secret: gordon_remote | |||
| 152 | + | commands: | |||
| 153 | + | - apk add --no-cache curl | |||
| 154 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 | |||
| 155 | + | -o /usr/local/bin/gordon | |||
| 156 | + | - chmod +x /usr/local/bin/gordon | |||
| 157 | + | - gordon push --build --remote "$GORDON_REMOTE" --no-confirm | |||
| 158 | + | ||||
| 159 | + | trigger: | |||
| 160 | + | event: | |||
| 161 | + | - tag | |||
| 162 | + | ``` | |||
| 163 | + | ||||
| 164 | + | ## Token Scopes Reference | |||
| 165 | + | ||||
| 166 | + | | Workflow | Required Scopes | | |||
| 167 | + | |----------|----------------| | |||
| 168 | + | | Build + push + deploy | `push,pull,admin:routes:read,admin:config:write` | | |||
| 169 | + | | Push only (no deploy) | `push,pull,admin:routes:read` | | |||
| 170 | + | | docker push (auto-deploy) | `push,pull` | | |||
| 171 | + | ||||
| 172 | + | ## Troubleshooting | |||
| 173 | + | ||||
| 174 | + | ### "failed to verify token" | |||
| 175 | + | ||||
| 176 | + | The token is invalid or has been revoked. Generate a new one. | |||
| 177 | + | ||||
| 178 | + | ### "no route configured for image" | |||
| 179 | + | ||||
| 180 | + | The route must exist before pushing. Create it with: | |||
| 181 | + | ||||
| 182 | + | ```bash | |||
| 183 | + | gordon routes add myapp.example.com myapp | |||
| 184 | + | # or for first deploy: | |||
| 185 | + | gordon bootstrap myapp.example.com myapp | |||
| 186 | + | ``` | |||
| 187 | + | ||||
| 188 | + | ### Version shows "latest" | |||
| 189 | + | ||||
| 190 | + | Gordon could not detect a version tag. Either: | |||
| 191 | + | - Tag your git repo: `git tag v1.0.0 && git push --tags` | |||
| 192 | + | - Pass explicitly: `gordon push --tag v1.0.0` | |||
| 193 | + | ||||
| 194 | + | ### Large images time out | |||
| 195 | + | ||||
| 196 | + | Gordon uploads in 50MB chunks. For very large images (> 1GB), the push may take several minutes. Ensure your CI runner timeout is sufficient. | |||
| 197 | + | ||||
| 198 | + | ## Related | |||
| 199 | + | ||||
| 200 | + | - [GitHub Actions](./github-actions.md) | |||
| 201 | + | - [GitLab CI](./gitlab-ci.md) | |||
| 202 | + | - [Deployment Overview](./index.md) | |||
| 203 | + | - [Authentication](../config/auth.md) | |||
| 204 | + | - [Push Command](../cli/push.md) | |||
M docs/deployment/github-actions.md +252 -55
| @@ -1,21 +1,26 @@ | |||
| 1 | 1 | # GitHub Actions Deployment | |
| 2 | 2 | ||
| 3 | - | Automated deployment with GitHub Actions using Gordon's official action. | |
| 3 | + | Two approaches for deploying with GitHub Actions: the `gordon push` CLI (recommended) or a Docker-based workflow using Gordon's official action. | |
| 4 | 4 | ||
| 5 | 5 | ## Prerequisites | |
| 6 | 6 | ||
| 7 | 7 | 1. Gordon server running with registry authentication enabled | |
| 8 | - | 2. Generated deployment token | |
| 8 | + | 2. Deployment token generated with the required scopes | |
| 9 | 9 | 3. GitHub repository secrets configured | |
| 10 | 10 | ||
| 11 | - | ## Quick Setup | |
| 11 | + | ## Recommended: gordon push | |
| 12 | 12 | ||
| 13 | - | ### 1. Generate Deployment Token | |
| 13 | + | Use the `gordon push` CLI for a lightweight, single-step build and deploy. | |
| 14 | + | ||
| 15 | + | ### 1. Generate Token | |
| 14 | 16 | ||
| 15 | 17 | On your Gordon server: | |
| 16 | 18 | ||
| 17 | 19 | ```bash | |
| 18 | - | gordon auth token generate --subject github-actions --scopes push,pull --expiry 0 | |
| 20 | + | gordon auth token generate \ | |
| 21 | + | --subject github-actions \ | |
| 22 | + | --scopes "push,pull,admin:routes:read,admin:config:write" \ | |
| 23 | + | --expiry 0 | |
| 19 | 24 | ``` | |
| 20 | 25 | ||
| 21 | 26 | Save the token output. | |
| @@ -26,70 +31,235 @@ In your repository: Settings → Secrets → Actions → New repository secret | |||
| 26 | 31 | ||
| 27 | 32 | | Secret | Value | | |
| 28 | 33 | |--------|-------| | |
| 29 | - | | `GORDON_REGISTRY` | `registry.mydomain.com` | | |
| 30 | - | | `GORDON_USERNAME` | `github-actions` | | |
| 31 | 34 | | `GORDON_TOKEN` | The generated token | | |
| 35 | + | | `GORDON_REMOTE` | `https://gordon.example.com` | | |
| 36 | + | ||
| 37 | + | ### 3. Install Gordon Binary | |
| 38 | + | ||
| 39 | + | Add this step to your workflow to download the Gordon binary: | |
| 40 | + | ||
| 41 | + | ```yaml | |
| 42 | + | - name: Install Gordon | |
| 43 | + | run: | | |
| 44 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 45 | + | chmod +x /usr/local/bin/gordon | |
| 46 | + | ``` | |
| 47 | + | ||
| 48 | + | ### 4. Workflow Examples | |
| 32 | 49 | ||
| 33 | - | ### 3. Create Workflow | |
| 50 | + | #### Deploy on Tag Push | |
| 34 | 51 | ||
| 35 | - | Create `.github/workflows/deploy.yml`: | |
| 52 | + | Gordon auto-detects the version from `$GITHUB_REF` (e.g., `refs/tags/v1.2.0` → `v1.2.0`). | |
| 36 | 53 | ||
| 37 | 54 | ```yaml | |
| 38 | 55 | name: Deploy to Gordon | |
| 39 | 56 | ||
| 40 | 57 | on: | |
| 41 | 58 | push: | |
| 42 | - | tags: | |
| 43 | - | - 'v*' | |
| 59 | + | tags: ['v*'] | |
| 44 | 60 | ||
| 45 | 61 | jobs: | |
| 46 | 62 | deploy: | |
| 47 | 63 | runs-on: ubuntu-latest | |
| 48 | 64 | steps: | |
| 49 | - | - uses: actions/checkout@v6 | |
| 65 | + | - uses: actions/checkout@v4 | |
| 66 | + | ||
| 67 | + | - name: Install Gordon | |
| 68 | + | run: | | |
| 69 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 70 | + | chmod +x /usr/local/bin/gordon | |
| 71 | + | ||
| 72 | + | - name: Build and Deploy | |
| 73 | + | env: | |
| 74 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |
| 75 | + | run: | | |
| 76 | + | gordon push --build \ | |
| 77 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |
| 78 | + | --no-confirm | |
| 79 | + | ``` | |
| 50 | 80 | ||
| 51 | - | - name: Deploy to Gordon | |
| 52 | - | uses: bnema/gordon/.github/actions/deploy@main | |
| 81 | + | #### Continuous Deploy on Main | |
| 82 | + | ||
| 83 | + | Deploy on every push to main. The version defaults to `latest` or the output of `git describe`. | |
| 84 | + | ||
| 85 | + | ```yaml | |
| 86 | + | name: Deploy to Gordon | |
| 87 | + | ||
| 88 | + | on: | |
| 89 | + | push: | |
| 90 | + | branches: | |
| 91 | + | - main | |
| 92 | + | ||
| 93 | + | jobs: | |
| 94 | + | deploy: | |
| 95 | + | runs-on: ubuntu-latest | |
| 96 | + | steps: | |
| 97 | + | - uses: actions/checkout@v4 | |
| 53 | 98 | with: | |
| 54 | - | registry: ${{ secrets.GORDON_REGISTRY }} | |
| 55 | - | username: ${{ secrets.GORDON_USERNAME }} | |
| 56 | - | password: ${{ secrets.GORDON_TOKEN }} | |
| 99 | + | fetch-depth: 0 | |
| 100 | + | ||
| 101 | + | - name: Install Gordon | |
| 102 | + | run: | | |
| 103 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 104 | + | chmod +x /usr/local/bin/gordon | |
| 105 | + | ||
| 106 | + | - name: Build and Deploy | |
| 107 | + | env: | |
| 108 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |
| 109 | + | run: | | |
| 110 | + | gordon push --build \ | |
| 111 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |
| 112 | + | --tag latest \ | |
| 113 | + | --no-confirm | |
| 57 | 114 | ``` | |
| 58 | 115 | ||
| 59 | - | ### 4. Deploy | |
| 116 | + | #### Manual Dispatch | |
| 60 | 117 | ||
| 61 | - | ```bash | |
| 62 | - | git tag v1.0.0 | |
| 63 | - | git push origin v1.0.0 | |
| 118 | + | Allow manual deployments with an optional tag input: | |
| 119 | + | ||
| 120 | + | ```yaml | |
| 121 | + | name: Deploy to Gordon | |
| 122 | + | ||
| 123 | + | on: | |
| 124 | + | workflow_dispatch: | |
| 125 | + | inputs: | |
| 126 | + | tag: | |
| 127 | + | description: 'Tag to deploy (leave empty to use git describe)' | |
| 128 | + | required: false | |
| 129 | + | ||
| 130 | + | jobs: | |
| 131 | + | deploy: | |
| 132 | + | runs-on: ubuntu-latest | |
| 133 | + | steps: | |
| 134 | + | - uses: actions/checkout@v4 | |
| 135 | + | with: | |
| 136 | + | ref: ${{ github.event.inputs.tag || github.ref }} | |
| 137 | + | fetch-depth: 0 | |
| 138 | + | ||
| 139 | + | - name: Install Gordon | |
| 140 | + | run: | | |
| 141 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 142 | + | chmod +x /usr/local/bin/gordon | |
| 143 | + | ||
| 144 | + | - name: Build and Deploy | |
| 145 | + | env: | |
| 146 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |
| 147 | + | run: | | |
| 148 | + | gordon push --build \ | |
| 149 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |
| 150 | + | ${{ github.event.inputs.tag && format('--tag {0}', github.event.inputs.tag) || '' }} \ | |
| 151 | + | --no-confirm | |
| 64 | 152 | ``` | |
| 65 | 153 | ||
| 66 | - | ## Action Reference | |
| 154 | + | #### Monorepo | |
| 67 | 155 | ||
| 68 | - | ### Inputs | |
| 156 | + | Deploy multiple services with separate `gordon push` calls: | |
| 69 | 157 | ||
| 70 | - | | Input | Required | Default | Description | | |
| 71 | - | |-------|----------|---------|-------------| | |
| 72 | - | | `registry` | Yes | - | Gordon registry URL | | |
| 73 | - | | `username` | Yes | - | Registry username | | |
| 74 | - | | `password` | Yes | - | Registry token | | |
| 75 | - | | `image` | No | repo name | Image name | | |
| 76 | - | | `tag` | No | git tag/SHA | Image tag | | |
| 77 | - | | `dockerfile` | No | `./Dockerfile` | Dockerfile path | | |
| 78 | - | | `context` | No | `.` | Build context | | |
| 79 | - | | `push-latest` | No | `false` | Also push :latest tag | | |
| 80 | - | | `platforms` | No | `linux/amd64` | Target platforms | | |
| 81 | - | | `build-args` | No | - | Build arguments | | |
| 158 | + | ```yaml | |
| 159 | + | name: Deploy Services | |
| 82 | 160 | ||
| 83 | - | ### Outputs | |
| 161 | + | on: | |
| 162 | + | push: | |
| 163 | + | tags: ['v*'] | |
| 84 | 164 | ||
| 85 | - | | Output | Description | | |
| 86 | - | |--------|-------------| | |
| 87 | - | | `image` | Full image name | | |
| 88 | - | | `tag` | Image tag | | |
| 165 | + | jobs: | |
| 166 | + | deploy: | |
| 167 | + | runs-on: ubuntu-latest | |
| 168 | + | steps: | |
| 169 | + | - uses: actions/checkout@v4 | |
| 170 | + | ||
| 171 | + | - name: Install Gordon | |
| 172 | + | run: | | |
| 173 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 174 | + | chmod +x /usr/local/bin/gordon | |
| 175 | + | ||
| 176 | + | - name: Deploy API | |
| 177 | + | env: | |
| 178 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |
| 179 | + | run: | | |
| 180 | + | gordon push --build \ | |
| 181 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |
| 182 | + | --file ./services/api/Dockerfile \ | |
| 183 | + | myapp-api \ | |
| 184 | + | --no-confirm | |
| 185 | + | ||
| 186 | + | - name: Deploy Web | |
| 187 | + | env: | |
| 188 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |
| 189 | + | run: | | |
| 190 | + | gordon push --build \ | |
| 191 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |
| 192 | + | --file ./services/web/Dockerfile \ | |
| 193 | + | myapp-web \ | |
| 194 | + | --no-confirm | |
| 195 | + | ``` | |
| 89 | 196 | ||
| 90 | - | ## Workflow Examples | |
| 197 | + | #### With Build Args | |
| 91 | 198 | ||
| 92 | - | ### Deploy on Tag Push | |
| 199 | + | Pass build arguments to the Docker build: | |
| 200 | + | ||
| 201 | + | ```yaml | |
| 202 | + | - name: Build and Deploy | |
| 203 | + | env: | |
| 204 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |
| 205 | + | run: | | |
| 206 | + | gordon push --build \ | |
| 207 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |
| 208 | + | --build-arg NODE_ENV=production \ | |
| 209 | + | --build-arg API_URL=https://api.example.com \ | |
| 210 | + | --build-arg BUILD_DATE=${{ github.event.head_commit.timestamp }} \ | |
| 211 | + | --no-confirm | |
| 212 | + | ``` | |
| 213 | + | ||
| 214 | + | ## Alternative: Docker-based Workflow | |
| 215 | + | ||
| 216 | + | For environments where installing the Gordon binary is not desired, use Docker directly to build and push to the Gordon registry. Gordon auto-deploys when it receives the image — no explicit deploy step is needed. | |
| 217 | + | ||
| 218 | + | ### Setup | |
| 219 | + | ||
| 220 | + | Add these secrets to your repository: | |
| 221 | + | ||
| 222 | + | | Secret | Value | | |
| 223 | + | |--------|-------| | |
| 224 | + | | `GORDON_REGISTRY` | `registry.gordon.example.com` | | |
| 225 | + | | `GORDON_USERNAME` | `github-actions` | | |
| 226 | + | | `GORDON_TOKEN` | The generated token | | |
| 227 | + | ||
| 228 | + | ### Workflow | |
| 229 | + | ||
| 230 | + | ```yaml | |
| 231 | + | name: Deploy to Gordon | |
| 232 | + | ||
| 233 | + | on: | |
| 234 | + | push: | |
| 235 | + | tags: ['v*'] | |
| 236 | + | ||
| 237 | + | jobs: | |
| 238 | + | deploy: | |
| 239 | + | runs-on: ubuntu-latest | |
| 240 | + | steps: | |
| 241 | + | - uses: actions/checkout@v4 | |
| 242 | + | ||
| 243 | + | - name: Login to Gordon Registry | |
| 244 | + | run: echo "${{ secrets.GORDON_TOKEN }}" | docker login ${{ secrets.GORDON_REGISTRY }} -u ${{ secrets.GORDON_USERNAME }} --password-stdin | |
| 245 | + | ||
| 246 | + | - name: Build and Push | |
| 247 | + | run: | | |
| 248 | + | docker build -t ${{ secrets.GORDON_REGISTRY }}/myapp:${{ github.ref_name }} . | |
| 249 | + | docker push ${{ secrets.GORDON_REGISTRY }}/myapp:${{ github.ref_name }} | |
| 250 | + | ``` | |
| 251 | + | ||
| 252 | + | ## Alternative: Gordon GitHub Action | |
| 253 | + | ||
| 254 | + | Use the official `bnema/gordon` action for a fully declarative workflow. This action handles login, build, and push in a single step. | |
| 255 | + | ||
| 256 | + | ### Setup | |
| 257 | + | ||
| 258 | + | Requires the same 3 secrets as the Docker-based workflow: `GORDON_REGISTRY`, `GORDON_USERNAME`, `GORDON_TOKEN`. | |
| 259 | + | ||
| 260 | + | ### Workflow Examples | |
| 261 | + | ||
| 262 | + | #### Deploy on Tag Push | |
| 93 | 263 | ||
| 94 | 264 | ```yaml | |
| 95 | 265 | name: Deploy to Gordon | |
| @@ -103,7 +273,7 @@ jobs: | |||
| 103 | 273 | deploy: | |
| 104 | 274 | runs-on: ubuntu-latest | |
| 105 | 275 | steps: | |
| 106 | - | - uses: actions/checkout@v6 | |
| 276 | + | - uses: actions/checkout@v4 | |
| 107 | 277 | ||
| 108 | 278 | - name: Deploy to Gordon | |
| 109 | 279 | uses: bnema/gordon/.github/actions/deploy@main | |
| @@ -113,7 +283,7 @@ jobs: | |||
| 113 | 283 | password: ${{ secrets.GORDON_TOKEN }} | |
| 114 | 284 | ``` | |
| 115 | 285 | ||
| 116 | - | ### Continuous Deployment | |
| 286 | + | #### Continuous Deployment | |
| 117 | 287 | ||
| 118 | 288 | Deploy on every push to main: | |
| 119 | 289 | ||
| @@ -129,7 +299,7 @@ jobs: | |||
| 129 | 299 | deploy: | |
| 130 | 300 | runs-on: ubuntu-latest | |
| 131 | 301 | steps: | |
| 132 | - | - uses: actions/checkout@v6 | |
| 302 | + | - uses: actions/checkout@v4 | |
| 133 | 303 | ||
| 134 | 304 | - name: Deploy to Gordon | |
| 135 | 305 | uses: bnema/gordon/.github/actions/deploy@main | |
| @@ -140,9 +310,9 @@ jobs: | |||
| 140 | 310 | push-latest: 'true' | |
| 141 | 311 | ``` | |
| 142 | 312 | ||
| 143 | - | ### Manual Deployment | |
| 313 | + | #### Manual Deployment | |
| 144 | 314 | ||
| 145 | - | Allow manual deployments with custom tag: | |
| 315 | + | Allow manual deployments with a custom tag: | |
| 146 | 316 | ||
| 147 | 317 | ```yaml | |
| 148 | 318 | name: Deploy to Gordon | |
| @@ -158,7 +328,7 @@ jobs: | |||
| 158 | 328 | deploy: | |
| 159 | 329 | runs-on: ubuntu-latest | |
| 160 | 330 | steps: | |
| 161 | - | - uses: actions/checkout@v6 | |
| 331 | + | - uses: actions/checkout@v4 | |
| 162 | 332 | with: | |
| 163 | 333 | ref: ${{ github.event.inputs.tag || github.ref }} | |
| 164 | 334 | ||
| @@ -171,7 +341,7 @@ jobs: | |||
| 171 | 341 | tag: ${{ github.event.inputs.tag }} | |
| 172 | 342 | ``` | |
| 173 | 343 | ||
| 174 | - | ### Monorepo Deployment | |
| 344 | + | #### Monorepo Deployment | |
| 175 | 345 | ||
| 176 | 346 | Deploy multiple services: | |
| 177 | 347 | ||
| @@ -187,7 +357,7 @@ jobs: | |||
| 187 | 357 | deploy-api: | |
| 188 | 358 | runs-on: ubuntu-latest | |
| 189 | 359 | steps: | |
| 190 | - | - uses: actions/checkout@v6 | |
| 360 | + | - uses: actions/checkout@v4 | |
| 191 | 361 | - uses: bnema/gordon/.github/actions/deploy@main | |
| 192 | 362 | with: | |
| 193 | 363 | registry: ${{ secrets.GORDON_REGISTRY }} | |
| @@ -200,7 +370,7 @@ jobs: | |||
| 200 | 370 | deploy-web: | |
| 201 | 371 | runs-on: ubuntu-latest | |
| 202 | 372 | steps: | |
| 203 | - | - uses: actions/checkout@v6 | |
| 373 | + | - uses: actions/checkout@v4 | |
| 204 | 374 | - uses: bnema/gordon/.github/actions/deploy@main | |
| 205 | 375 | with: | |
| 206 | 376 | registry: ${{ secrets.GORDON_REGISTRY }} | |
| @@ -211,7 +381,7 @@ jobs: | |||
| 211 | 381 | context: ./services/web | |
| 212 | 382 | ``` | |
| 213 | 383 | ||
| 214 | - | ### With Build Arguments | |
| 384 | + | #### With Build Arguments | |
| 215 | 385 | ||
| 216 | 386 | ```yaml | |
| 217 | 387 | - uses: bnema/gordon/.github/actions/deploy@main | |
| @@ -225,7 +395,7 @@ jobs: | |||
| 225 | 395 | BUILD_DATE=${{ github.event.head_commit.timestamp }} | |
| 226 | 396 | ``` | |
| 227 | 397 | ||
| 228 | - | ### Multi-Platform Build | |
| 398 | + | #### Multi-Platform Build | |
| 229 | 399 | ||
| 230 | 400 | ```yaml | |
| 231 | 401 | - uses: bnema/gordon/.github/actions/deploy@main | |
| @@ -236,7 +406,31 @@ jobs: | |||
| 236 | 406 | platforms: linux/amd64,linux/arm64 | |
| 237 | 407 | ``` | |
| 238 | 408 | ||
| 239 | - | ## Deployment Summary | |
| 409 | + | ### Action Reference | |
| 410 | + | ||
| 411 | + | #### Inputs | |
| 412 | + | ||
| 413 | + | | Input | Required | Default | Description | | |
| 414 | + | |-------|----------|---------|-------------| | |
| 415 | + | | `registry` | Yes | - | Gordon registry URL | | |
| 416 | + | | `username` | Yes | - | Registry username | | |
| 417 | + | | `password` | Yes | - | Registry token | | |
| 418 | + | | `image` | No | repo name | Image name | | |
| 419 | + | | `tag` | No | git tag/SHA | Image tag | | |
| 420 | + | | `dockerfile` | No | `./Dockerfile` | Dockerfile path | | |
| 421 | + | | `context` | No | `.` | Build context | | |
| 422 | + | | `push-latest` | No | `false` | Also push :latest tag | | |
| 423 | + | | `platforms` | No | `linux/amd64` | Target platforms | | |
| 424 | + | | `build-args` | No | - | Build arguments | | |
| 425 | + | ||
| 426 | + | #### Outputs | |
| 427 | + | ||
| 428 | + | | Output | Description | | |
| 429 | + | |--------|-------------| | |
| 430 | + | | `image` | Full image name | | |
| 431 | + | | `tag` | Image tag | | |
| 432 | + | ||
| 433 | + | #### Deployment Summary | |
| 240 | 434 | ||
| 241 | 435 | Add a deployment summary to your workflow: | |
| 242 | 436 | ||
| @@ -277,6 +471,9 @@ Error: unauthorized: authentication required | |||
| 277 | 471 | ||
| 278 | 472 | ## Related | |
| 279 | 473 | ||
| 280 | - | - [Authentication](../config/auth.md) | |
| 474 | + | - [GitLab CI](./gitlab-ci.md) | |
| 475 | + | - [Generic CI](./generic-ci.md) | |
| 281 | 476 | - [Deployment Overview](./index.md) | |
| 477 | + | - [Authentication](../config/auth.md) | |
| 478 | + | - [Push Command](../cli/push.md) | |
| 282 | 479 | - [Rollback](./rollback.md) | |
| @@ -1,21 +1,26 @@ | |||||
| 1 | # GitHub Actions Deployment | 1 | # GitHub Actions Deployment | ||
| 2 | 2 | ||||
| 3 | - | Automated deployment with GitHub Actions using Gordon's official action. | 3 | + | Two approaches for deploying with GitHub Actions: the `gordon push` CLI (recommended) or a Docker-based workflow using Gordon's official action. |
| 4 | 4 | ||||
| 5 | ## Prerequisites | 5 | ## Prerequisites | ||
| 6 | 6 | ||||
| 7 | 1. Gordon server running with registry authentication enabled | 7 | 1. Gordon server running with registry authentication enabled | ||
| 8 | - | 2. Generated deployment token | 8 | + | 2. Deployment token generated with the required scopes |
| 9 | 3. GitHub repository secrets configured | 9 | 3. GitHub repository secrets configured | ||
| 10 | 10 | ||||
| 11 | - | ## Quick Setup | 11 | + | ## Recommended: gordon push |
| 12 | 12 | ||||
| 13 | - | ### 1. Generate Deployment Token | 13 | + | Use the `gordon push` CLI for a lightweight, single-step build and deploy. |
| 14 | + | ||||
| 15 | + | ### 1. Generate Token | |||
| 14 | 16 | ||||
| 15 | On your Gordon server: | 17 | On your Gordon server: | ||
| 16 | 18 | ||||
| 17 | ```bash | 19 | ```bash | ||
| 18 | - | gordon auth token generate --subject github-actions --scopes push,pull --expiry 0 | 20 | + | gordon auth token generate \ |
| 21 | + | --subject github-actions \ | |||
| 22 | + | --scopes "push,pull,admin:routes:read,admin:config:write" \ | |||
| 23 | + | --expiry 0 | |||
| 19 | ``` | 24 | ``` | ||
| 20 | 25 | ||||
| 21 | Save the token output. | 26 | Save the token output. | ||
| @@ -26,70 +31,235 @@ In your repository: Settings → Secrets → Actions → New repository secret | |||||
| 26 | 31 | ||||
| 27 | | Secret | Value | | 32 | | Secret | Value | | ||
| 28 | |--------|-------| | 33 | |--------|-------| | ||
| 29 | - | | `GORDON_REGISTRY` | `registry.mydomain.com` | | |||
| 30 | - | | `GORDON_USERNAME` | `github-actions` | | |||
| 31 | | `GORDON_TOKEN` | The generated token | | 34 | | `GORDON_TOKEN` | The generated token | | ||
| 35 | + | | `GORDON_REMOTE` | `https://gordon.example.com` | | |||
| 36 | + | ||||
| 37 | + | ### 3. Install Gordon Binary | |||
| 38 | + | ||||
| 39 | + | Add this step to your workflow to download the Gordon binary: | |||
| 40 | + | ||||
| 41 | + | ```yaml | |||
| 42 | + | - name: Install Gordon | |||
| 43 | + | run: | | |||
| 44 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 45 | + | chmod +x /usr/local/bin/gordon | |||
| 46 | + | ``` | |||
| 47 | + | ||||
| 48 | + | ### 4. Workflow Examples | |||
| 32 | 49 | ||||
| 33 | - | ### 3. Create Workflow | 50 | + | #### Deploy on Tag Push |
| 34 | 51 | ||||
| 35 | - | Create `.github/workflows/deploy.yml`: | 52 | + | Gordon auto-detects the version from `$GITHUB_REF` (e.g., `refs/tags/v1.2.0` → `v1.2.0`). |
| 36 | 53 | ||||
| 37 | ```yaml | 54 | ```yaml | ||
| 38 | name: Deploy to Gordon | 55 | name: Deploy to Gordon | ||
| 39 | 56 | ||||
| 40 | on: | 57 | on: | ||
| 41 | push: | 58 | push: | ||
| 42 | - | tags: | 59 | + | tags: ['v*'] |
| 43 | - | - 'v*' | |||
| 44 | 60 | ||||
| 45 | jobs: | 61 | jobs: | ||
| 46 | deploy: | 62 | deploy: | ||
| 47 | runs-on: ubuntu-latest | 63 | runs-on: ubuntu-latest | ||
| 48 | steps: | 64 | steps: | ||
| 49 | - | - uses: actions/checkout@v6 | 65 | + | - uses: actions/checkout@v4 |
| 66 | + | ||||
| 67 | + | - name: Install Gordon | |||
| 68 | + | run: | | |||
| 69 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 70 | + | chmod +x /usr/local/bin/gordon | |||
| 71 | + | ||||
| 72 | + | - name: Build and Deploy | |||
| 73 | + | env: | |||
| 74 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |||
| 75 | + | run: | | |||
| 76 | + | gordon push --build \ | |||
| 77 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |||
| 78 | + | --no-confirm | |||
| 79 | + | ``` | |||
| 50 | 80 | ||||
| 51 | - | - name: Deploy to Gordon | 81 | + | #### Continuous Deploy on Main |
| 52 | - | uses: bnema/gordon/.github/actions/deploy@main | 82 | + | |
| 83 | + | Deploy on every push to main. The version defaults to `latest` or the output of `git describe`. | |||
| 84 | + | ||||
| 85 | + | ```yaml | |||
| 86 | + | name: Deploy to Gordon | |||
| 87 | + | ||||
| 88 | + | on: | |||
| 89 | + | push: | |||
| 90 | + | branches: | |||
| 91 | + | - main | |||
| 92 | + | ||||
| 93 | + | jobs: | |||
| 94 | + | deploy: | |||
| 95 | + | runs-on: ubuntu-latest | |||
| 96 | + | steps: | |||
| 97 | + | - uses: actions/checkout@v4 | |||
| 53 | with: | 98 | with: | ||
| 54 | - | registry: ${{ secrets.GORDON_REGISTRY }} | 99 | + | fetch-depth: 0 |
| 55 | - | username: ${{ secrets.GORDON_USERNAME }} | 100 | + | |
| 56 | - | password: ${{ secrets.GORDON_TOKEN }} | 101 | + | - name: Install Gordon |
| 102 | + | run: | | |||
| 103 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 104 | + | chmod +x /usr/local/bin/gordon | |||
| 105 | + | ||||
| 106 | + | - name: Build and Deploy | |||
| 107 | + | env: | |||
| 108 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |||
| 109 | + | run: | | |||
| 110 | + | gordon push --build \ | |||
| 111 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |||
| 112 | + | --tag latest \ | |||
| 113 | + | --no-confirm | |||
| 57 | ``` | 114 | ``` | ||
| 58 | 115 | ||||
| 59 | - | ### 4. Deploy | 116 | + | #### Manual Dispatch |
| 60 | 117 | ||||
| 61 | - | ```bash | 118 | + | Allow manual deployments with an optional tag input: |
| 62 | - | git tag v1.0.0 | 119 | + | |
| 63 | - | git push origin v1.0.0 | 120 | + | ```yaml |
| 121 | + | name: Deploy to Gordon | |||
| 122 | + | ||||
| 123 | + | on: | |||
| 124 | + | workflow_dispatch: | |||
| 125 | + | inputs: | |||
| 126 | + | tag: | |||
| 127 | + | description: 'Tag to deploy (leave empty to use git describe)' | |||
| 128 | + | required: false | |||
| 129 | + | ||||
| 130 | + | jobs: | |||
| 131 | + | deploy: | |||
| 132 | + | runs-on: ubuntu-latest | |||
| 133 | + | steps: | |||
| 134 | + | - uses: actions/checkout@v4 | |||
| 135 | + | with: | |||
| 136 | + | ref: ${{ github.event.inputs.tag || github.ref }} | |||
| 137 | + | fetch-depth: 0 | |||
| 138 | + | ||||
| 139 | + | - name: Install Gordon | |||
| 140 | + | run: | | |||
| 141 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 142 | + | chmod +x /usr/local/bin/gordon | |||
| 143 | + | ||||
| 144 | + | - name: Build and Deploy | |||
| 145 | + | env: | |||
| 146 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |||
| 147 | + | run: | | |||
| 148 | + | gordon push --build \ | |||
| 149 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |||
| 150 | + | ${{ github.event.inputs.tag && format('--tag {0}', github.event.inputs.tag) || '' }} \ | |||
| 151 | + | --no-confirm | |||
| 64 | ``` | 152 | ``` | ||
| 65 | 153 | ||||
| 66 | - | ## Action Reference | 154 | + | #### Monorepo |
| 67 | 155 | ||||
| 68 | - | ### Inputs | 156 | + | Deploy multiple services with separate `gordon push` calls: |
| 69 | 157 | ||||
| 70 | - | | Input | Required | Default | Description | | 158 | + | ```yaml |
| 71 | - | |-------|----------|---------|-------------| | 159 | + | name: Deploy Services |
| 72 | - | | `registry` | Yes | - | Gordon registry URL | | |||
| 73 | - | | `username` | Yes | - | Registry username | | |||
| 74 | - | | `password` | Yes | - | Registry token | | |||
| 75 | - | | `image` | No | repo name | Image name | | |||
| 76 | - | | `tag` | No | git tag/SHA | Image tag | | |||
| 77 | - | | `dockerfile` | No | `./Dockerfile` | Dockerfile path | | |||
| 78 | - | | `context` | No | `.` | Build context | | |||
| 79 | - | | `push-latest` | No | `false` | Also push :latest tag | | |||
| 80 | - | | `platforms` | No | `linux/amd64` | Target platforms | | |||
| 81 | - | | `build-args` | No | - | Build arguments | | |||
| 82 | 160 | ||||
| 83 | - | ### Outputs | 161 | + | on: |
| 162 | + | push: | |||
| 163 | + | tags: ['v*'] | |||
| 84 | 164 | ||||
| 85 | - | | Output | Description | | 165 | + | jobs: |
| 86 | - | |--------|-------------| | 166 | + | deploy: |
| 87 | - | | `image` | Full image name | | 167 | + | runs-on: ubuntu-latest |
| 88 | - | | `tag` | Image tag | | 168 | + | steps: |
| 169 | + | - uses: actions/checkout@v4 | |||
| 170 | + | ||||
| 171 | + | - name: Install Gordon | |||
| 172 | + | run: | | |||
| 173 | + | curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 174 | + | chmod +x /usr/local/bin/gordon | |||
| 175 | + | ||||
| 176 | + | - name: Deploy API | |||
| 177 | + | env: | |||
| 178 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |||
| 179 | + | run: | | |||
| 180 | + | gordon push --build \ | |||
| 181 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |||
| 182 | + | --file ./services/api/Dockerfile \ | |||
| 183 | + | myapp-api \ | |||
| 184 | + | --no-confirm | |||
| 185 | + | ||||
| 186 | + | - name: Deploy Web | |||
| 187 | + | env: | |||
| 188 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |||
| 189 | + | run: | | |||
| 190 | + | gordon push --build \ | |||
| 191 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |||
| 192 | + | --file ./services/web/Dockerfile \ | |||
| 193 | + | myapp-web \ | |||
| 194 | + | --no-confirm | |||
| 195 | + | ``` | |||
| 89 | 196 | ||||
| 90 | - | ## Workflow Examples | 197 | + | #### With Build Args |
| 91 | 198 | ||||
| 92 | - | ### Deploy on Tag Push | 199 | + | Pass build arguments to the Docker build: |
| 200 | + | ||||
| 201 | + | ```yaml | |||
| 202 | + | - name: Build and Deploy | |||
| 203 | + | env: | |||
| 204 | + | GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }} | |||
| 205 | + | run: | | |||
| 206 | + | gordon push --build \ | |||
| 207 | + | --remote ${{ secrets.GORDON_REMOTE }} \ | |||
| 208 | + | --build-arg NODE_ENV=production \ | |||
| 209 | + | --build-arg API_URL=https://api.example.com \ | |||
| 210 | + | --build-arg BUILD_DATE=${{ github.event.head_commit.timestamp }} \ | |||
| 211 | + | --no-confirm | |||
| 212 | + | ``` | |||
| 213 | + | ||||
| 214 | + | ## Alternative: Docker-based Workflow | |||
| 215 | + | ||||
| 216 | + | For environments where installing the Gordon binary is not desired, use Docker directly to build and push to the Gordon registry. Gordon auto-deploys when it receives the image — no explicit deploy step is needed. | |||
| 217 | + | ||||
| 218 | + | ### Setup | |||
| 219 | + | ||||
| 220 | + | Add these secrets to your repository: | |||
| 221 | + | ||||
| 222 | + | | Secret | Value | | |||
| 223 | + | |--------|-------| | |||
| 224 | + | | `GORDON_REGISTRY` | `registry.gordon.example.com` | | |||
| 225 | + | | `GORDON_USERNAME` | `github-actions` | | |||
| 226 | + | | `GORDON_TOKEN` | The generated token | | |||
| 227 | + | ||||
| 228 | + | ### Workflow | |||
| 229 | + | ||||
| 230 | + | ```yaml | |||
| 231 | + | name: Deploy to Gordon | |||
| 232 | + | ||||
| 233 | + | on: | |||
| 234 | + | push: | |||
| 235 | + | tags: ['v*'] | |||
| 236 | + | ||||
| 237 | + | jobs: | |||
| 238 | + | deploy: | |||
| 239 | + | runs-on: ubuntu-latest | |||
| 240 | + | steps: | |||
| 241 | + | - uses: actions/checkout@v4 | |||
| 242 | + | ||||
| 243 | + | - name: Login to Gordon Registry | |||
| 244 | + | run: echo "${{ secrets.GORDON_TOKEN }}" | docker login ${{ secrets.GORDON_REGISTRY }} -u ${{ secrets.GORDON_USERNAME }} --password-stdin | |||
| 245 | + | ||||
| 246 | + | - name: Build and Push | |||
| 247 | + | run: | | |||
| 248 | + | docker build -t ${{ secrets.GORDON_REGISTRY }}/myapp:${{ github.ref_name }} . | |||
| 249 | + | docker push ${{ secrets.GORDON_REGISTRY }}/myapp:${{ github.ref_name }} | |||
| 250 | + | ``` | |||
| 251 | + | ||||
| 252 | + | ## Alternative: Gordon GitHub Action | |||
| 253 | + | ||||
| 254 | + | Use the official `bnema/gordon` action for a fully declarative workflow. This action handles login, build, and push in a single step. | |||
| 255 | + | ||||
| 256 | + | ### Setup | |||
| 257 | + | ||||
| 258 | + | Requires the same 3 secrets as the Docker-based workflow: `GORDON_REGISTRY`, `GORDON_USERNAME`, `GORDON_TOKEN`. | |||
| 259 | + | ||||
| 260 | + | ### Workflow Examples | |||
| 261 | + | ||||
| 262 | + | #### Deploy on Tag Push | |||
| 93 | 263 | ||||
| 94 | ```yaml | 264 | ```yaml | ||
| 95 | name: Deploy to Gordon | 265 | name: Deploy to Gordon | ||
| @@ -103,7 +273,7 @@ jobs: | |||||
| 103 | deploy: | 273 | deploy: | ||
| 104 | runs-on: ubuntu-latest | 274 | runs-on: ubuntu-latest | ||
| 105 | steps: | 275 | steps: | ||
| 106 | - | - uses: actions/checkout@v6 | 276 | + | - uses: actions/checkout@v4 |
| 107 | 277 | ||||
| 108 | - name: Deploy to Gordon | 278 | - name: Deploy to Gordon | ||
| 109 | uses: bnema/gordon/.github/actions/deploy@main | 279 | uses: bnema/gordon/.github/actions/deploy@main | ||
| @@ -113,7 +283,7 @@ jobs: | |||||
| 113 | password: ${{ secrets.GORDON_TOKEN }} | 283 | password: ${{ secrets.GORDON_TOKEN }} | ||
| 114 | ``` | 284 | ``` | ||
| 115 | 285 | ||||
| 116 | - | ### Continuous Deployment | 286 | + | #### Continuous Deployment |
| 117 | 287 | ||||
| 118 | Deploy on every push to main: | 288 | Deploy on every push to main: | ||
| 119 | 289 | ||||
| @@ -129,7 +299,7 @@ jobs: | |||||
| 129 | deploy: | 299 | deploy: | ||
| 130 | runs-on: ubuntu-latest | 300 | runs-on: ubuntu-latest | ||
| 131 | steps: | 301 | steps: | ||
| 132 | - | - uses: actions/checkout@v6 | 302 | + | - uses: actions/checkout@v4 |
| 133 | 303 | ||||
| 134 | - name: Deploy to Gordon | 304 | - name: Deploy to Gordon | ||
| 135 | uses: bnema/gordon/.github/actions/deploy@main | 305 | uses: bnema/gordon/.github/actions/deploy@main | ||
| @@ -140,9 +310,9 @@ jobs: | |||||
| 140 | push-latest: 'true' | 310 | push-latest: 'true' | ||
| 141 | ``` | 311 | ``` | ||
| 142 | 312 | ||||
| 143 | - | ### Manual Deployment | 313 | + | #### Manual Deployment |
| 144 | 314 | ||||
| 145 | - | Allow manual deployments with custom tag: | 315 | + | Allow manual deployments with a custom tag: |
| 146 | 316 | ||||
| 147 | ```yaml | 317 | ```yaml | ||
| 148 | name: Deploy to Gordon | 318 | name: Deploy to Gordon | ||
| @@ -158,7 +328,7 @@ jobs: | |||||
| 158 | deploy: | 328 | deploy: | ||
| 159 | runs-on: ubuntu-latest | 329 | runs-on: ubuntu-latest | ||
| 160 | steps: | 330 | steps: | ||
| 161 | - | - uses: actions/checkout@v6 | 331 | + | - uses: actions/checkout@v4 |
| 162 | with: | 332 | with: | ||
| 163 | ref: ${{ github.event.inputs.tag || github.ref }} | 333 | ref: ${{ github.event.inputs.tag || github.ref }} | ||
| 164 | 334 | ||||
| @@ -171,7 +341,7 @@ jobs: | |||||
| 171 | tag: ${{ github.event.inputs.tag }} | 341 | tag: ${{ github.event.inputs.tag }} | ||
| 172 | ``` | 342 | ``` | ||
| 173 | 343 | ||||
| 174 | - | ### Monorepo Deployment | 344 | + | #### Monorepo Deployment |
| 175 | 345 | ||||
| 176 | Deploy multiple services: | 346 | Deploy multiple services: | ||
| 177 | 347 | ||||
| @@ -187,7 +357,7 @@ jobs: | |||||
| 187 | deploy-api: | 357 | deploy-api: | ||
| 188 | runs-on: ubuntu-latest | 358 | runs-on: ubuntu-latest | ||
| 189 | steps: | 359 | steps: | ||
| 190 | - | - uses: actions/checkout@v6 | 360 | + | - uses: actions/checkout@v4 |
| 191 | - uses: bnema/gordon/.github/actions/deploy@main | 361 | - uses: bnema/gordon/.github/actions/deploy@main | ||
| 192 | with: | 362 | with: | ||
| 193 | registry: ${{ secrets.GORDON_REGISTRY }} | 363 | registry: ${{ secrets.GORDON_REGISTRY }} | ||
| @@ -200,7 +370,7 @@ jobs: | |||||
| 200 | deploy-web: | 370 | deploy-web: | ||
| 201 | runs-on: ubuntu-latest | 371 | runs-on: ubuntu-latest | ||
| 202 | steps: | 372 | steps: | ||
| 203 | - | - uses: actions/checkout@v6 | 373 | + | - uses: actions/checkout@v4 |
| 204 | - uses: bnema/gordon/.github/actions/deploy@main | 374 | - uses: bnema/gordon/.github/actions/deploy@main | ||
| 205 | with: | 375 | with: | ||
| 206 | registry: ${{ secrets.GORDON_REGISTRY }} | 376 | registry: ${{ secrets.GORDON_REGISTRY }} | ||
| @@ -211,7 +381,7 @@ jobs: | |||||
| 211 | context: ./services/web | 381 | context: ./services/web | ||
| 212 | ``` | 382 | ``` | ||
| 213 | 383 | ||||
| 214 | - | ### With Build Arguments | 384 | + | #### With Build Arguments |
| 215 | 385 | ||||
| 216 | ```yaml | 386 | ```yaml | ||
| 217 | - uses: bnema/gordon/.github/actions/deploy@main | 387 | - uses: bnema/gordon/.github/actions/deploy@main | ||
| @@ -225,7 +395,7 @@ jobs: | |||||
| 225 | BUILD_DATE=${{ github.event.head_commit.timestamp }} | 395 | BUILD_DATE=${{ github.event.head_commit.timestamp }} | ||
| 226 | ``` | 396 | ``` | ||
| 227 | 397 | ||||
| 228 | - | ### Multi-Platform Build | 398 | + | #### Multi-Platform Build |
| 229 | 399 | ||||
| 230 | ```yaml | 400 | ```yaml | ||
| 231 | - uses: bnema/gordon/.github/actions/deploy@main | 401 | - uses: bnema/gordon/.github/actions/deploy@main | ||
| @@ -236,7 +406,31 @@ jobs: | |||||
| 236 | platforms: linux/amd64,linux/arm64 | 406 | platforms: linux/amd64,linux/arm64 | ||
| 237 | ``` | 407 | ``` | ||
| 238 | 408 | ||||
| 239 | - | ## Deployment Summary | 409 | + | ### Action Reference |
| 410 | + | ||||
| 411 | + | #### Inputs | |||
| 412 | + | ||||
| 413 | + | | Input | Required | Default | Description | | |||
| 414 | + | |-------|----------|---------|-------------| | |||
| 415 | + | | `registry` | Yes | - | Gordon registry URL | | |||
| 416 | + | | `username` | Yes | - | Registry username | | |||
| 417 | + | | `password` | Yes | - | Registry token | | |||
| 418 | + | | `image` | No | repo name | Image name | | |||
| 419 | + | | `tag` | No | git tag/SHA | Image tag | | |||
| 420 | + | | `dockerfile` | No | `./Dockerfile` | Dockerfile path | | |||
| 421 | + | | `context` | No | `.` | Build context | | |||
| 422 | + | | `push-latest` | No | `false` | Also push :latest tag | | |||
| 423 | + | | `platforms` | No | `linux/amd64` | Target platforms | | |||
| 424 | + | | `build-args` | No | - | Build arguments | | |||
| 425 | + | ||||
| 426 | + | #### Outputs | |||
| 427 | + | ||||
| 428 | + | | Output | Description | | |||
| 429 | + | |--------|-------------| | |||
| 430 | + | | `image` | Full image name | | |||
| 431 | + | | `tag` | Image tag | | |||
| 432 | + | ||||
| 433 | + | #### Deployment Summary | |||
| 240 | 434 | ||||
| 241 | Add a deployment summary to your workflow: | 435 | Add a deployment summary to your workflow: | ||
| 242 | 436 | ||||
| @@ -277,6 +471,9 @@ Error: unauthorized: authentication required | |||||
| 277 | 471 | ||||
| 278 | ## Related | 472 | ## Related | ||
| 279 | 473 | ||||
| 280 | - | - [Authentication](../config/auth.md) | 474 | + | - [GitLab CI](./gitlab-ci.md) |
| 475 | + | - [Generic CI](./generic-ci.md) | |||
| 281 | - [Deployment Overview](./index.md) | 476 | - [Deployment Overview](./index.md) | ||
| 477 | + | - [Authentication](../config/auth.md) | |||
| 478 | + | - [Push Command](../cli/push.md) | |||
| 282 | - [Rollback](./rollback.md) | 479 | - [Rollback](./rollback.md) | ||
A docs/deployment/gitlab-ci.md +211 -0
| @@ -0,0 +1,211 @@ | |||
| 1 | + | # GitLab CI/CD Deployment | |
| 2 | + | ||
| 3 | + | Automated deployment with GitLab CI/CD using Gordon's push command. | |
| 4 | + | ||
| 5 | + | ## Prerequisites | |
| 6 | + | ||
| 7 | + | 1. Gordon server running with registry authentication enabled | |
| 8 | + | 2. Generated deployment token | |
| 9 | + | 3. GitLab CI/CD variables configured | |
| 10 | + | ||
| 11 | + | ## Quick Setup | |
| 12 | + | ||
| 13 | + | ### 1. Generate Deployment Token | |
| 14 | + | ||
| 15 | + | On your Gordon server: | |
| 16 | + | ||
| 17 | + | ```bash | |
| 18 | + | gordon auth token generate \ | |
| 19 | + | --subject gitlab-ci \ | |
| 20 | + | --scopes "push,pull,admin:routes:read,admin:config:write" \ | |
| 21 | + | --expiry 0 | |
| 22 | + | ``` | |
| 23 | + | ||
| 24 | + | ### 2. Add CI/CD Variables | |
| 25 | + | ||
| 26 | + | In your project: Settings > CI/CD > Variables | |
| 27 | + | ||
| 28 | + | | Variable | Value | Protected | Masked | | |
| 29 | + | |----------|-------|-----------|--------| | |
| 30 | + | | `GORDON_TOKEN` | The generated token | Yes | Yes | | |
| 31 | + | | `GORDON_REMOTE` | `https://gordon.example.com` | Yes | No | | |
| 32 | + | ||
| 33 | + | ### 3. Create Pipeline | |
| 34 | + | ||
| 35 | + | Create `.gitlab-ci.yml`: | |
| 36 | + | ||
| 37 | + | ```yaml | |
| 38 | + | deploy: | |
| 39 | + | stage: deploy | |
| 40 | + | image: docker:24 | |
| 41 | + | services: | |
| 42 | + | - docker:24-dind | |
| 43 | + | before_script: | |
| 44 | + | - apk add --no-cache curl | |
| 45 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 46 | + | - chmod +x /usr/local/bin/gordon | |
| 47 | + | script: | |
| 48 | + | - gordon push --build | |
| 49 | + | --remote "$GORDON_REMOTE" | |
| 50 | + | --token "$GORDON_TOKEN" | |
| 51 | + | --no-confirm | |
| 52 | + | only: | |
| 53 | + | - tags | |
| 54 | + | ``` | |
| 55 | + | ||
| 56 | + | Gordon auto-detects the version from `$CI_COMMIT_TAG`. | |
| 57 | + | ||
| 58 | + | ## Pipeline Examples | |
| 59 | + | ||
| 60 | + | ### Deploy on Tag Push | |
| 61 | + | ||
| 62 | + | ```yaml | |
| 63 | + | stages: | |
| 64 | + | - deploy | |
| 65 | + | ||
| 66 | + | deploy: | |
| 67 | + | stage: deploy | |
| 68 | + | image: docker:24 | |
| 69 | + | services: | |
| 70 | + | - docker:24-dind | |
| 71 | + | before_script: | |
| 72 | + | - apk add --no-cache curl | |
| 73 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 74 | + | - chmod +x /usr/local/bin/gordon | |
| 75 | + | script: | |
| 76 | + | - gordon push --build | |
| 77 | + | --remote "$GORDON_REMOTE" | |
| 78 | + | --token "$GORDON_TOKEN" | |
| 79 | + | --no-confirm | |
| 80 | + | rules: | |
| 81 | + | - if: $CI_COMMIT_TAG | |
| 82 | + | ``` | |
| 83 | + | ||
| 84 | + | ### Continuous Deployment | |
| 85 | + | ||
| 86 | + | Deploy on every push to main: | |
| 87 | + | ||
| 88 | + | ```yaml | |
| 89 | + | deploy: | |
| 90 | + | stage: deploy | |
| 91 | + | image: docker:24 | |
| 92 | + | services: | |
| 93 | + | - docker:24-dind | |
| 94 | + | before_script: | |
| 95 | + | - apk add --no-cache curl | |
| 96 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 97 | + | - chmod +x /usr/local/bin/gordon | |
| 98 | + | script: | |
| 99 | + | - gordon push --build | |
| 100 | + | --remote "$GORDON_REMOTE" | |
| 101 | + | --token "$GORDON_TOKEN" | |
| 102 | + | --no-confirm | |
| 103 | + | rules: | |
| 104 | + | - if: $CI_COMMIT_BRANCH == "main" | |
| 105 | + | ``` | |
| 106 | + | ||
| 107 | + | ### Manual Deployment | |
| 108 | + | ||
| 109 | + | ```yaml | |
| 110 | + | deploy: | |
| 111 | + | stage: deploy | |
| 112 | + | image: docker:24 | |
| 113 | + | services: | |
| 114 | + | - docker:24-dind | |
| 115 | + | before_script: | |
| 116 | + | - apk add --no-cache curl | |
| 117 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 118 | + | - chmod +x /usr/local/bin/gordon | |
| 119 | + | script: | |
| 120 | + | - gordon push --build | |
| 121 | + | --remote "$GORDON_REMOTE" | |
| 122 | + | --token "$GORDON_TOKEN" | |
| 123 | + | --no-confirm | |
| 124 | + | when: manual | |
| 125 | + | ``` | |
| 126 | + | ||
| 127 | + | ### With Build Arguments | |
| 128 | + | ||
| 129 | + | ```yaml | |
| 130 | + | deploy: | |
| 131 | + | stage: deploy | |
| 132 | + | image: docker:24 | |
| 133 | + | services: | |
| 134 | + | - docker:24-dind | |
| 135 | + | before_script: | |
| 136 | + | - apk add --no-cache curl | |
| 137 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |
| 138 | + | - chmod +x /usr/local/bin/gordon | |
| 139 | + | script: | |
| 140 | + | - gordon push --build | |
| 141 | + | --remote "$GORDON_REMOTE" | |
| 142 | + | --token "$GORDON_TOKEN" | |
| 143 | + | --build-arg NODE_ENV=production | |
| 144 | + | --build-arg API_URL=https://api.example.com | |
| 145 | + | --no-confirm | |
| 146 | + | rules: | |
| 147 | + | - if: $CI_COMMIT_TAG | |
| 148 | + | ``` | |
| 149 | + | ||
| 150 | + | ## Alternative: Docker-based Pipeline | |
| 151 | + | ||
| 152 | + | For environments where installing the Gordon binary is not desired: | |
| 153 | + | ||
| 154 | + | ```yaml | |
| 155 | + | deploy: | |
| 156 | + | stage: deploy | |
| 157 | + | image: docker:24 | |
| 158 | + | services: | |
| 159 | + | - docker:24-dind | |
| 160 | + | script: | |
| 161 | + | - echo "$GORDON_TOKEN" | docker login "$GORDON_REGISTRY" -u "$GORDON_USERNAME" --password-stdin | |
| 162 | + | - docker build -t "$GORDON_REGISTRY/myapp:$CI_COMMIT_TAG" . | |
| 163 | + | - docker push "$GORDON_REGISTRY/myapp:$CI_COMMIT_TAG" | |
| 164 | + | rules: | |
| 165 | + | - if: $CI_COMMIT_TAG | |
| 166 | + | ``` | |
| 167 | + | ||
| 168 | + | This requires additional CI/CD variables: `GORDON_REGISTRY` and `GORDON_USERNAME`. | |
| 169 | + | Gordon auto-deploys when it receives the image. | |
| 170 | + | ||
| 171 | + | ## Version Detection | |
| 172 | + | ||
| 173 | + | Gordon automatically detects the version tag from GitLab CI environment variables: | |
| 174 | + | ||
| 175 | + | | Variable | Example | Result | | |
| 176 | + | |----------|---------|--------| | |
| 177 | + | | `$CI_COMMIT_TAG` | `v1.2.0` | Tag `v1.2.0` | | |
| 178 | + | | No tag | - | Falls back to `git describe` or `latest` | | |
| 179 | + | ||
| 180 | + | ## Troubleshooting | |
| 181 | + | ||
| 182 | + | ### Authentication Failed | |
| 183 | + | ||
| 184 | + | ``` | |
| 185 | + | Error: failed to verify token | |
| 186 | + | ``` | |
| 187 | + | ||
| 188 | + | Verify `GORDON_TOKEN` is correctly set and the token has not been revoked. | |
| 189 | + | ||
| 190 | + | ### Docker-in-Docker Issues | |
| 191 | + | ||
| 192 | + | If using `docker:dind`, ensure the service is properly configured: | |
| 193 | + | ||
| 194 | + | ```yaml | |
| 195 | + | services: | |
| 196 | + | - docker:24-dind | |
| 197 | + | variables: | |
| 198 | + | DOCKER_TLS_CERTDIR: "/certs" | |
| 199 | + | ``` | |
| 200 | + | ||
| 201 | + | ### Build Context | |
| 202 | + | ||
| 203 | + | GitLab CI clones your repository automatically. The build context defaults to the repository root. | |
| 204 | + | ||
| 205 | + | ## Related | |
| 206 | + | ||
| 207 | + | - [GitHub Actions](./github-actions.md) | |
| 208 | + | - [Generic CI](./generic-ci.md) | |
| 209 | + | - [Deployment Overview](./index.md) | |
| 210 | + | - [Authentication](../config/auth.md) | |
| 211 | + | - [Push Command](../cli/push.md) | |
| @@ -0,0 +1,211 @@ | |||||
| 1 | + | # GitLab CI/CD Deployment | |||
| 2 | + | ||||
| 3 | + | Automated deployment with GitLab CI/CD using Gordon's push command. | |||
| 4 | + | ||||
| 5 | + | ## Prerequisites | |||
| 6 | + | ||||
| 7 | + | 1. Gordon server running with registry authentication enabled | |||
| 8 | + | 2. Generated deployment token | |||
| 9 | + | 3. GitLab CI/CD variables configured | |||
| 10 | + | ||||
| 11 | + | ## Quick Setup | |||
| 12 | + | ||||
| 13 | + | ### 1. Generate Deployment Token | |||
| 14 | + | ||||
| 15 | + | On your Gordon server: | |||
| 16 | + | ||||
| 17 | + | ```bash | |||
| 18 | + | gordon auth token generate \ | |||
| 19 | + | --subject gitlab-ci \ | |||
| 20 | + | --scopes "push,pull,admin:routes:read,admin:config:write" \ | |||
| 21 | + | --expiry 0 | |||
| 22 | + | ``` | |||
| 23 | + | ||||
| 24 | + | ### 2. Add CI/CD Variables | |||
| 25 | + | ||||
| 26 | + | In your project: Settings > CI/CD > Variables | |||
| 27 | + | ||||
| 28 | + | | Variable | Value | Protected | Masked | | |||
| 29 | + | |----------|-------|-----------|--------| | |||
| 30 | + | | `GORDON_TOKEN` | The generated token | Yes | Yes | | |||
| 31 | + | | `GORDON_REMOTE` | `https://gordon.example.com` | Yes | No | | |||
| 32 | + | ||||
| 33 | + | ### 3. Create Pipeline | |||
| 34 | + | ||||
| 35 | + | Create `.gitlab-ci.yml`: | |||
| 36 | + | ||||
| 37 | + | ```yaml | |||
| 38 | + | deploy: | |||
| 39 | + | stage: deploy | |||
| 40 | + | image: docker:24 | |||
| 41 | + | services: | |||
| 42 | + | - docker:24-dind | |||
| 43 | + | before_script: | |||
| 44 | + | - apk add --no-cache curl | |||
| 45 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 46 | + | - chmod +x /usr/local/bin/gordon | |||
| 47 | + | script: | |||
| 48 | + | - gordon push --build | |||
| 49 | + | --remote "$GORDON_REMOTE" | |||
| 50 | + | --token "$GORDON_TOKEN" | |||
| 51 | + | --no-confirm | |||
| 52 | + | only: | |||
| 53 | + | - tags | |||
| 54 | + | ``` | |||
| 55 | + | ||||
| 56 | + | Gordon auto-detects the version from `$CI_COMMIT_TAG`. | |||
| 57 | + | ||||
| 58 | + | ## Pipeline Examples | |||
| 59 | + | ||||
| 60 | + | ### Deploy on Tag Push | |||
| 61 | + | ||||
| 62 | + | ```yaml | |||
| 63 | + | stages: | |||
| 64 | + | - deploy | |||
| 65 | + | ||||
| 66 | + | deploy: | |||
| 67 | + | stage: deploy | |||
| 68 | + | image: docker:24 | |||
| 69 | + | services: | |||
| 70 | + | - docker:24-dind | |||
| 71 | + | before_script: | |||
| 72 | + | - apk add --no-cache curl | |||
| 73 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 74 | + | - chmod +x /usr/local/bin/gordon | |||
| 75 | + | script: | |||
| 76 | + | - gordon push --build | |||
| 77 | + | --remote "$GORDON_REMOTE" | |||
| 78 | + | --token "$GORDON_TOKEN" | |||
| 79 | + | --no-confirm | |||
| 80 | + | rules: | |||
| 81 | + | - if: $CI_COMMIT_TAG | |||
| 82 | + | ``` | |||
| 83 | + | ||||
| 84 | + | ### Continuous Deployment | |||
| 85 | + | ||||
| 86 | + | Deploy on every push to main: | |||
| 87 | + | ||||
| 88 | + | ```yaml | |||
| 89 | + | deploy: | |||
| 90 | + | stage: deploy | |||
| 91 | + | image: docker:24 | |||
| 92 | + | services: | |||
| 93 | + | - docker:24-dind | |||
| 94 | + | before_script: | |||
| 95 | + | - apk add --no-cache curl | |||
| 96 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 97 | + | - chmod +x /usr/local/bin/gordon | |||
| 98 | + | script: | |||
| 99 | + | - gordon push --build | |||
| 100 | + | --remote "$GORDON_REMOTE" | |||
| 101 | + | --token "$GORDON_TOKEN" | |||
| 102 | + | --no-confirm | |||
| 103 | + | rules: | |||
| 104 | + | - if: $CI_COMMIT_BRANCH == "main" | |||
| 105 | + | ``` | |||
| 106 | + | ||||
| 107 | + | ### Manual Deployment | |||
| 108 | + | ||||
| 109 | + | ```yaml | |||
| 110 | + | deploy: | |||
| 111 | + | stage: deploy | |||
| 112 | + | image: docker:24 | |||
| 113 | + | services: | |||
| 114 | + | - docker:24-dind | |||
| 115 | + | before_script: | |||
| 116 | + | - apk add --no-cache curl | |||
| 117 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 118 | + | - chmod +x /usr/local/bin/gordon | |||
| 119 | + | script: | |||
| 120 | + | - gordon push --build | |||
| 121 | + | --remote "$GORDON_REMOTE" | |||
| 122 | + | --token "$GORDON_TOKEN" | |||
| 123 | + | --no-confirm | |||
| 124 | + | when: manual | |||
| 125 | + | ``` | |||
| 126 | + | ||||
| 127 | + | ### With Build Arguments | |||
| 128 | + | ||||
| 129 | + | ```yaml | |||
| 130 | + | deploy: | |||
| 131 | + | stage: deploy | |||
| 132 | + | image: docker:24 | |||
| 133 | + | services: | |||
| 134 | + | - docker:24-dind | |||
| 135 | + | before_script: | |||
| 136 | + | - apk add --no-cache curl | |||
| 137 | + | - curl -fsSL https://github.com/bnema/gordon/releases/latest/download/gordon_linux_amd64 -o /usr/local/bin/gordon | |||
| 138 | + | - chmod +x /usr/local/bin/gordon | |||
| 139 | + | script: | |||
| 140 | + | - gordon push --build | |||
| 141 | + | --remote "$GORDON_REMOTE" | |||
| 142 | + | --token "$GORDON_TOKEN" | |||
| 143 | + | --build-arg NODE_ENV=production | |||
| 144 | + | --build-arg API_URL=https://api.example.com | |||
| 145 | + | --no-confirm | |||
| 146 | + | rules: | |||
| 147 | + | - if: $CI_COMMIT_TAG | |||
| 148 | + | ``` | |||
| 149 | + | ||||
| 150 | + | ## Alternative: Docker-based Pipeline | |||
| 151 | + | ||||
| 152 | + | For environments where installing the Gordon binary is not desired: | |||
| 153 | + | ||||
| 154 | + | ```yaml | |||
| 155 | + | deploy: | |||
| 156 | + | stage: deploy | |||
| 157 | + | image: docker:24 | |||
| 158 | + | services: | |||
| 159 | + | - docker:24-dind | |||
| 160 | + | script: | |||
| 161 | + | - echo "$GORDON_TOKEN" | docker login "$GORDON_REGISTRY" -u "$GORDON_USERNAME" --password-stdin | |||
| 162 | + | - docker build -t "$GORDON_REGISTRY/myapp:$CI_COMMIT_TAG" . | |||
| 163 | + | - docker push "$GORDON_REGISTRY/myapp:$CI_COMMIT_TAG" | |||
| 164 | + | rules: | |||
| 165 | + | - if: $CI_COMMIT_TAG | |||
| 166 | + | ``` | |||
| 167 | + | ||||
| 168 | + | This requires additional CI/CD variables: `GORDON_REGISTRY` and `GORDON_USERNAME`. | |||
| 169 | + | Gordon auto-deploys when it receives the image. | |||
| 170 | + | ||||
| 171 | + | ## Version Detection | |||
| 172 | + | ||||
| 173 | + | Gordon automatically detects the version tag from GitLab CI environment variables: | |||
| 174 | + | ||||
| 175 | + | | Variable | Example | Result | | |||
| 176 | + | |----------|---------|--------| | |||
| 177 | + | | `$CI_COMMIT_TAG` | `v1.2.0` | Tag `v1.2.0` | | |||
| 178 | + | | No tag | - | Falls back to `git describe` or `latest` | | |||
| 179 | + | ||||
| 180 | + | ## Troubleshooting | |||
| 181 | + | ||||
| 182 | + | ### Authentication Failed | |||
| 183 | + | ||||
| 184 | + | ``` | |||
| 185 | + | Error: failed to verify token | |||
| 186 | + | ``` | |||
| 187 | + | ||||
| 188 | + | Verify `GORDON_TOKEN` is correctly set and the token has not been revoked. | |||
| 189 | + | ||||
| 190 | + | ### Docker-in-Docker Issues | |||
| 191 | + | ||||
| 192 | + | If using `docker:dind`, ensure the service is properly configured: | |||
| 193 | + | ||||
| 194 | + | ```yaml | |||
| 195 | + | services: | |||
| 196 | + | - docker:24-dind | |||
| 197 | + | variables: | |||
| 198 | + | DOCKER_TLS_CERTDIR: "/certs" | |||
| 199 | + | ``` | |||
| 200 | + | ||||
| 201 | + | ### Build Context | |||
| 202 | + | ||||
| 203 | + | GitLab CI clones your repository automatically. The build context defaults to the repository root. | |||
| 204 | + | ||||
| 205 | + | ## Related | |||
| 206 | + | ||||
| 207 | + | - [GitHub Actions](./github-actions.md) | |||
| 208 | + | - [Generic CI](./generic-ci.md) | |||
| 209 | + | - [Deployment Overview](./index.md) | |||
| 210 | + | - [Authentication](../config/auth.md) | |||
| 211 | + | - [Push Command](../cli/push.md) | |||
M docs/deployment/index.md +101 -115
| @@ -1,41 +1,104 @@ | |||
| 1 | 1 | # Deployment Overview | |
| 2 | 2 | ||
| 3 | - | Strategies for deploying applications with Gordon. | |
| 3 | + | Gordon deploys containers when you push images to its built-in registry. Three deployment methods are available depending on your workflow and infrastructure. | |
| 4 | 4 | ||
| 5 | - | ## Deployment Methods | |
| 5 | + | ## Recommended: gordon push | |
| 6 | 6 | ||
| 7 | - | | Method | Use Case | | |
| 8 | - | |--------|----------| | |
| 9 | - | | Manual Push | Development, one-off deploys | | |
| 10 | - | | GitHub Actions | Automated CI/CD | | |
| 11 | - | | GitLab CI | Automated CI/CD | | |
| 12 | - | | Generic CI | Any CI/CD system | | |
| 7 | + | `gordon push --build --remote` is the simplest way to build, push, and deploy from CI/CD pipelines. | |
| 13 | 8 | ||
| 14 | - | ## Basic Deployment Workflow | |
| 9 | + | - Single command: build + push + deploy | |
| 10 | + | - Single secret (`GORDON_TOKEN`): auto-exchanges for a short-lived registry token | |
| 11 | + | - Auto-detects version from CI environment (`$GITHUB_REF`, `$CI_COMMIT_TAG`, `$BUILD_SOURCEBRANCH`, or `git describe`) | |
| 12 | + | - Chunked uploads (50MB chunks) — works behind Cloudflare and restrictive proxies | |
| 15 | 13 | ||
| 16 | - | ### 1. Build Locally | |
| 14 | + | ```bash | |
| 15 | + | gordon push --build --remote https://gordon.example.com --no-confirm | |
| 16 | + | ``` | |
| 17 | + | ||
| 18 | + | ## All Deployment Methods | |
| 19 | + | ||
| 20 | + | | Method | Best For | Secrets Needed | Registry Access | Deploy Control | | |
| 21 | + | |--------|----------|----------------|-----------------|----------------| | |
| 22 | + | | `gordon push` (Recommended) | CI/CD pipelines | 1 (`GORDON_TOKEN`) | Via gordon domain (HTTPS) | Explicit (CLI-triggered) | | |
| 23 | + | | `docker push` | Simple setups, existing Docker workflows | 2 (`username` + `token`) | Via gordon domain (HTTPS) | Automatic (event-based) | | |
| 24 | + | | Docker labels + auto-route | GitOps, zero-config deploys | 2 (`username` + `token`) | Via gordon domain (HTTPS) | Automatic (label-driven) | | |
| 25 | + | ||
| 26 | + | ### Method 1: gordon push (Recommended) | |
| 27 | + | ||
| 28 | + | The Gordon CLI handles authentication, image building, and deployment in a single step. | |
| 29 | + | ||
| 30 | + | - Single token handles everything: admin API access + registry auth via automatic token exchange | |
| 31 | + | - Version tag auto-detected from `$GITHUB_REF`, `$CI_COMMIT_TAG`, `$BUILD_SOURCEBRANCH`, or `git describe` | |
| 32 | + | - Use `--no-deploy` for push-only workflows (useful for staging images without triggering deployment) | |
| 33 | + | - Requires the Gordon binary on the CI runner | |
| 17 | 34 | ||
| 18 | 35 | ```bash | |
| 19 | - | docker build -t myapp . | |
| 36 | + | # Build, push, and deploy | |
| 37 | + | gordon push --build --remote https://gordon.example.com --no-confirm | |
| 38 | + | ||
| 39 | + | # Push only, no deploy | |
| 40 | + | gordon push --build --remote https://gordon.example.com --no-deploy --no-confirm | |
| 20 | 41 | ``` | |
| 21 | 42 | ||
| 22 | - | ### 2. Tag for Registry | |
| 43 | + | ### Method 2: docker push | |
| 44 | + | ||
| 45 | + | Standard Docker workflow — no Gordon binary required on the runner. | |
| 46 | + | ||
| 47 | + | - Use `docker login`, `docker build`, and `docker push` as usual | |
| 48 | + | - Gordon auto-deploys when it receives the image (event-based, no explicit trigger needed) | |
| 49 | + | - No Gordon binary needed on the CI runner | |
| 50 | + | - Registry endpoint is `gordon.example.com` (not a separate registry host) | |
| 23 | 51 | ||
| 24 | 52 | ```bash | |
| 25 | - | docker tag myapp registry.mydomain.com/myapp:latest | |
| 53 | + | docker login -u ci-bot -p "$GORDON_TOKEN" gordon.example.com | |
| 54 | + | docker build -t gordon.example.com/myapp:v1.2.0 . | |
| 55 | + | docker push gordon.example.com/myapp:v1.2.0 | |
| 56 | + | ``` | |
| 57 | + | ||
| 58 | + | ### Method 3: Docker labels + auto-route | |
| 59 | + | ||
| 60 | + | Add a `gordon.domain` label to your image and Gordon creates the route automatically on push. | |
| 61 | + | ||
| 62 | + | - Add `gordon.domain=app.example.com` label to your Dockerfile | |
| 63 | + | - Push image — Gordon creates or updates the route without manual config | |
| 64 | + | - Gated by the `auto_route_allowed_domains` allowlist in `gordon.toml` | |
| 65 | + | - Best for GitOps workflows where routes are defined alongside the application | |
| 66 | + | ||
| 67 | + | ```dockerfile | |
| 68 | + | LABEL gordon.domain="app.example.com" | |
| 26 | 69 | ``` | |
| 27 | 70 | ||
| 28 | - | ### 3. Push to Deploy | |
| 71 | + | See [Auto-Route](../config/auto-route.md) for configuration details. | |
| 72 | + | ||
| 73 | + | ## Registry Access | |
| 74 | + | ||
| 75 | + | Gordon's registry is served through the main gordon domain over HTTPS on port 443. The internal registry port (5000) is never exposed externally. All push methods use `https://gordon.example.com/v2/...`. | |
| 76 | + | ||
| 77 | + | ### Network Topologies | |
| 78 | + | ||
| 79 | + | | Setup | Configuration | Use Case | | |
| 80 | + | |-------|--------------|----------| | |
| 81 | + | | Public (default) | `auth.enabled = true` | Hosted CI runners (GitHub Actions, GitLab CI) | | |
| 82 | + | | Tailscale only | `registry_allowed_ips = ["100.64.0.0/10"]` | Self-hosted runners in Tailnet | | |
| 83 | + | | Localhost only | `auth.enabled = false` | Local development, single-machine deploys | | |
| 84 | + | ||
| 85 | + | ## Token Setup | |
| 29 | 86 | ||
| 30 | 87 | ```bash | |
| 31 | - | docker push registry.mydomain.com/myapp:latest | |
| 88 | + | # For gordon push (recommended) — needs admin scopes for route resolution and deploy | |
| 89 | + | gordon auth token generate \ | |
| 90 | + | --subject ci-bot \ | |
| 91 | + | --scopes "push,pull,admin:routes:read,admin:config:write" \ | |
| 92 | + | --expiry 0 | |
| 93 | + | ||
| 94 | + | # For docker push — registry scopes only | |
| 95 | + | gordon auth token generate \ | |
| 96 | + | --subject ci-bot \ | |
| 97 | + | --scopes "push,pull" \ | |
| 98 | + | --expiry 0 | |
| 32 | 99 | ``` | |
| 33 | 100 | ||
| 34 | - | Gordon automatically: | |
| 35 | - | 1. Receives the image | |
| 36 | - | 2. Deploys a new container | |
| 37 | - | 3. Routes traffic to it | |
| 38 | - | 4. Stops the old container | |
| 101 | + | Set the generated token as `GORDON_TOKEN` in your CI environment. | |
| 39 | 102 | ||
| 40 | 103 | ## Version Strategies | |
| 41 | 104 | ||
| @@ -44,54 +107,48 @@ Gordon automatically: | |||
| 44 | 107 | Always deploy the most recent build: | |
| 45 | 108 | ||
| 46 | 109 | ```bash | |
| 47 | - | docker tag myapp registry.mydomain.com/myapp:latest | |
| 48 | - | docker push registry.mydomain.com/myapp:latest | |
| 110 | + | docker tag myapp gordon.example.com/myapp:latest | |
| 111 | + | docker push gordon.example.com/myapp:latest | |
| 49 | 112 | ``` | |
| 50 | 113 | ||
| 51 | - | Configure route: | |
| 52 | 114 | ```toml | |
| 53 | 115 | [routes] | |
| 54 | - | "app.mydomain.com" = "myapp:latest" | |
| 116 | + | "app.example.com" = "myapp:latest" | |
| 55 | 117 | ``` | |
| 56 | 118 | ||
| 57 | 119 | ### Semantic Versioning | |
| 58 | 120 | ||
| 59 | - | Pin to specific versions: | |
| 121 | + | Pin routes to specific versions and update config to roll forward: | |
| 60 | 122 | ||
| 61 | 123 | ```bash | |
| 62 | - | docker tag myapp registry.mydomain.com/myapp:v2.1.0 | |
| 63 | - | docker push registry.mydomain.com/myapp:v2.1.0 | |
| 124 | + | docker tag myapp gordon.example.com/myapp:v2.1.0 | |
| 125 | + | docker push gordon.example.com/myapp:v2.1.0 | |
| 64 | 126 | ``` | |
| 65 | 127 | ||
| 66 | - | Configure route: | |
| 67 | 128 | ```toml | |
| 68 | 129 | [routes] | |
| 69 | - | "app.mydomain.com" = "myapp:v2.1.0" | |
| 130 | + | "app.example.com" = "myapp:v2.1.0" | |
| 70 | 131 | ``` | |
| 71 | 132 | ||
| 72 | - | Update config to deploy new version: | |
| 73 | - | ```toml | |
| 74 | - | [routes] | |
| 75 | - | "app.mydomain.com" = "myapp:v2.2.0" | |
| 76 | - | ``` | |
| 133 | + | To deploy a new version, update the tag in `gordon.toml` and push the new image. | |
| 77 | 134 | ||
| 78 | 135 | ### Git SHA Tags | |
| 79 | 136 | ||
| 80 | - | Tag with commit hash for traceability: | |
| 137 | + | Tag with commit hash for full traceability: | |
| 81 | 138 | ||
| 82 | 139 | ```bash | |
| 83 | 140 | VERSION=$(git rev-parse --short HEAD) | |
| 84 | - | docker tag myapp registry.mydomain.com/myapp:$VERSION | |
| 85 | - | docker push registry.mydomain.com/myapp:$VERSION | |
| 141 | + | docker tag myapp gordon.example.com/myapp:$VERSION | |
| 142 | + | docker push gordon.example.com/myapp:$VERSION | |
| 86 | 143 | ``` | |
| 87 | 144 | ||
| 88 | 145 | ## Zero-Downtime Deployment | |
| 89 | 146 | ||
| 90 | 147 | Gordon performs zero-downtime deployments by default: | |
| 91 | 148 | ||
| 92 | - | 1. **New container starts** while old is still running | |
| 93 | - | 2. **Health check** waits for new container readiness | |
| 94 | - | 3. **Traffic switches** to new container | |
| 149 | + | 1. **New container starts** while the old one is still running | |
| 150 | + | 2. **Health check** waits for the new container to become ready | |
| 151 | + | 3. **Traffic switches** to the new container | |
| 95 | 152 | 4. **Old container stops** after traffic moves | |
| 96 | 153 | ||
| 97 | 154 | ``` | |
| @@ -103,83 +160,12 @@ New Container: [══════════════════ | |||
| 103 | 160 | ↑ start ↑ traffic routed | |
| 104 | 161 | ``` | |
| 105 | 162 | ||
| 106 | - | ## Environment-Specific Deployments | |
| 107 | - | ||
| 108 | - | ### Development | |
| 109 | - | ||
| 110 | - | ```toml | |
| 111 | - | [routes] | |
| 112 | - | "dev.mydomain.com" = "myapp:latest" | |
| 113 | - | ``` | |
| 114 | - | ||
| 115 | - | ```bash | |
| 116 | - | docker push registry.mydomain.com/myapp:latest | |
| 117 | - | ``` | |
| 118 | - | ||
| 119 | - | ### Staging | |
| 120 | - | ||
| 121 | - | ```toml | |
| 122 | - | [routes] | |
| 123 | - | "staging.mydomain.com" = "myapp:staging" | |
| 124 | - | ``` | |
| 125 | - | ||
| 126 | - | ```bash | |
| 127 | - | docker tag myapp registry.mydomain.com/myapp:staging | |
| 128 | - | docker push registry.mydomain.com/myapp:staging | |
| 129 | - | ``` | |
| 130 | - | ||
| 131 | - | ### Production | |
| 132 | - | ||
| 133 | - | ```toml | |
| 134 | - | [routes] | |
| 135 | - | "app.mydomain.com" = "myapp:v2.1.0" | |
| 136 | - | ``` | |
| 137 | - | ||
| 138 | - | ```bash | |
| 139 | - | docker tag myapp registry.mydomain.com/myapp:v2.1.0 | |
| 140 | - | docker push registry.mydomain.com/myapp:v2.1.0 | |
| 141 | - | # Then update gordon.toml and reload | |
| 142 | - | ``` | |
| 143 | - | ||
| 144 | - | ## Deployment Checklist | |
| 145 | - | ||
| 146 | - | Before deploying: | |
| 147 | - | ||
| 148 | - | - [ ] Build passes locally | |
| 149 | - | - [ ] Tests pass | |
| 150 | - | - [ ] Environment file configured (`~/.gordon/env/app_mydomain_com.env`) | |
| 151 | - | - [ ] DNS pointing to Gordon server | |
| 152 | - | - [ ] Route configured in `gordon.toml` | |
| 153 | - | ||
| 154 | - | After deploying: | |
| 155 | - | ||
| 156 | - | - [ ] Container starts successfully | |
| 157 | - | - [ ] Application responds to requests | |
| 158 | - | - [ ] Logs show no errors | |
| 159 | - | - [ ] Health checks pass | |
| 160 | - | ||
| 161 | - | ## Monitoring Deployments | |
| 162 | - | ||
| 163 | - | ### Watch Logs | |
| 164 | - | ||
| 165 | - | ```bash | |
| 166 | - | gordon logs -f | |
| 167 | - | ``` | |
| 168 | - | ||
| 169 | - | ### Check Container Status | |
| 170 | - | ||
| 171 | - | ```bash | |
| 172 | - | docker ps | grep gordon | |
| 173 | - | ``` | |
| 174 | - | ||
| 175 | - | ### Verify Routing | |
| 176 | - | ||
| 177 | - | ```bash | |
| 178 | - | curl -I https://app.mydomain.com | |
| 179 | - | ``` | |
| 180 | - | ||
| 181 | 163 | ## Related | |
| 182 | 164 | ||
| 183 | 165 | - [GitHub Actions](./github-actions.md) | |
| 166 | + | - [GitLab CI](./gitlab-ci.md) | |
| 167 | + | - [Generic CI](./generic-ci.md) | |
| 184 | 168 | - [Rollback](./rollback.md) | |
| 185 | 169 | - [Routes Configuration](../config/routes.md) | |
| 170 | + | - [Authentication](../config/auth.md) | |
| 171 | + | - [Auto-Route](../config/auto-route.md) | |
| @@ -1,41 +1,104 @@ | |||||
| 1 | # Deployment Overview | 1 | # Deployment Overview | ||
| 2 | 2 | ||||
| 3 | - | Strategies for deploying applications with Gordon. | 3 | + | Gordon deploys containers when you push images to its built-in registry. Three deployment methods are available depending on your workflow and infrastructure. |
| 4 | 4 | ||||
| 5 | - | ## Deployment Methods | 5 | + | ## Recommended: gordon push |
| 6 | 6 | ||||
| 7 | - | | Method | Use Case | | 7 | + | `gordon push --build --remote` is the simplest way to build, push, and deploy from CI/CD pipelines. |
| 8 | - | |--------|----------| | |||
| 9 | - | | Manual Push | Development, one-off deploys | | |||
| 10 | - | | GitHub Actions | Automated CI/CD | | |||
| 11 | - | | GitLab CI | Automated CI/CD | | |||
| 12 | - | | Generic CI | Any CI/CD system | | |||
| 13 | 8 | ||||
| 14 | - | ## Basic Deployment Workflow | 9 | + | - Single command: build + push + deploy |
| 10 | + | - Single secret (`GORDON_TOKEN`): auto-exchanges for a short-lived registry token | |||
| 11 | + | - Auto-detects version from CI environment (`$GITHUB_REF`, `$CI_COMMIT_TAG`, `$BUILD_SOURCEBRANCH`, or `git describe`) | |||
| 12 | + | - Chunked uploads (50MB chunks) — works behind Cloudflare and restrictive proxies | |||
| 15 | 13 | ||||
| 16 | - | ### 1. Build Locally | 14 | + | ```bash |
| 15 | + | gordon push --build --remote https://gordon.example.com --no-confirm | |||
| 16 | + | ``` | |||
| 17 | + | ||||
| 18 | + | ## All Deployment Methods | |||
| 19 | + | ||||
| 20 | + | | Method | Best For | Secrets Needed | Registry Access | Deploy Control | | |||
| 21 | + | |--------|----------|----------------|-----------------|----------------| | |||
| 22 | + | | `gordon push` (Recommended) | CI/CD pipelines | 1 (`GORDON_TOKEN`) | Via gordon domain (HTTPS) | Explicit (CLI-triggered) | | |||
| 23 | + | | `docker push` | Simple setups, existing Docker workflows | 2 (`username` + `token`) | Via gordon domain (HTTPS) | Automatic (event-based) | | |||
| 24 | + | | Docker labels + auto-route | GitOps, zero-config deploys | 2 (`username` + `token`) | Via gordon domain (HTTPS) | Automatic (label-driven) | | |||
| 25 | + | ||||
| 26 | + | ### Method 1: gordon push (Recommended) | |||
| 27 | + | ||||
| 28 | + | The Gordon CLI handles authentication, image building, and deployment in a single step. | |||
| 29 | + | ||||
| 30 | + | - Single token handles everything: admin API access + registry auth via automatic token exchange | |||
| 31 | + | - Version tag auto-detected from `$GITHUB_REF`, `$CI_COMMIT_TAG`, `$BUILD_SOURCEBRANCH`, or `git describe` | |||
| 32 | + | - Use `--no-deploy` for push-only workflows (useful for staging images without triggering deployment) | |||
| 33 | + | - Requires the Gordon binary on the CI runner | |||
| 17 | 34 | ||||
| 18 | ```bash | 35 | ```bash | ||
| 19 | - | docker build -t myapp . | 36 | + | # Build, push, and deploy |
| 37 | + | gordon push --build --remote https://gordon.example.com --no-confirm | |||
| 38 | + | ||||
| 39 | + | # Push only, no deploy | |||
| 40 | + | gordon push --build --remote https://gordon.example.com --no-deploy --no-confirm | |||
| 20 | ``` | 41 | ``` | ||
| 21 | 42 | ||||
| 22 | - | ### 2. Tag for Registry | 43 | + | ### Method 2: docker push |
| 44 | + | ||||
| 45 | + | Standard Docker workflow — no Gordon binary required on the runner. | |||
| 46 | + | ||||
| 47 | + | - Use `docker login`, `docker build`, and `docker push` as usual | |||
| 48 | + | - Gordon auto-deploys when it receives the image (event-based, no explicit trigger needed) | |||
| 49 | + | - No Gordon binary needed on the CI runner | |||
| 50 | + | - Registry endpoint is `gordon.example.com` (not a separate registry host) | |||
| 23 | 51 | ||||
| 24 | ```bash | 52 | ```bash | ||
| 25 | - | docker tag myapp registry.mydomain.com/myapp:latest | 53 | + | docker login -u ci-bot -p "$GORDON_TOKEN" gordon.example.com |
| 54 | + | docker build -t gordon.example.com/myapp:v1.2.0 . | |||
| 55 | + | docker push gordon.example.com/myapp:v1.2.0 | |||
| 56 | + | ``` | |||
| 57 | + | ||||
| 58 | + | ### Method 3: Docker labels + auto-route | |||
| 59 | + | ||||
| 60 | + | Add a `gordon.domain` label to your image and Gordon creates the route automatically on push. | |||
| 61 | + | ||||
| 62 | + | - Add `gordon.domain=app.example.com` label to your Dockerfile | |||
| 63 | + | - Push image — Gordon creates or updates the route without manual config | |||
| 64 | + | - Gated by the `auto_route_allowed_domains` allowlist in `gordon.toml` | |||
| 65 | + | - Best for GitOps workflows where routes are defined alongside the application | |||
| 66 | + | ||||
| 67 | + | ```dockerfile | |||
| 68 | + | LABEL gordon.domain="app.example.com" | |||
| 26 | ``` | 69 | ``` | ||
| 27 | 70 | ||||
| 28 | - | ### 3. Push to Deploy | 71 | + | See [Auto-Route](../config/auto-route.md) for configuration details. |
| 72 | + | ||||
| 73 | + | ## Registry Access | |||
| 74 | + | ||||
| 75 | + | Gordon's registry is served through the main gordon domain over HTTPS on port 443. The internal registry port (5000) is never exposed externally. All push methods use `https://gordon.example.com/v2/...`. | |||
| 76 | + | ||||
| 77 | + | ### Network Topologies | |||
| 78 | + | ||||
| 79 | + | | Setup | Configuration | Use Case | | |||
| 80 | + | |-------|--------------|----------| | |||
| 81 | + | | Public (default) | `auth.enabled = true` | Hosted CI runners (GitHub Actions, GitLab CI) | | |||
| 82 | + | | Tailscale only | `registry_allowed_ips = ["100.64.0.0/10"]` | Self-hosted runners in Tailnet | | |||
| 83 | + | | Localhost only | `auth.enabled = false` | Local development, single-machine deploys | | |||
| 84 | + | ||||
| 85 | + | ## Token Setup | |||
| 29 | 86 | ||||
| 30 | ```bash | 87 | ```bash | ||
| 31 | - | docker push registry.mydomain.com/myapp:latest | 88 | + | # For gordon push (recommended) — needs admin scopes for route resolution and deploy |
| 89 | + | gordon auth token generate \ | |||
| 90 | + | --subject ci-bot \ | |||
| 91 | + | --scopes "push,pull,admin:routes:read,admin:config:write" \ | |||
| 92 | + | --expiry 0 | |||
| 93 | + | ||||
| 94 | + | # For docker push — registry scopes only | |||
| 95 | + | gordon auth token generate \ | |||
| 96 | + | --subject ci-bot \ | |||
| 97 | + | --scopes "push,pull" \ | |||
| 98 | + | --expiry 0 | |||
| 32 | ``` | 99 | ``` | ||
| 33 | 100 | ||||
| 34 | - | Gordon automatically: | 101 | + | Set the generated token as `GORDON_TOKEN` in your CI environment. |
| 35 | - | 1. Receives the image | |||
| 36 | - | 2. Deploys a new container | |||
| 37 | - | 3. Routes traffic to it | |||
| 38 | - | 4. Stops the old container | |||
| 39 | 102 | ||||
| 40 | ## Version Strategies | 103 | ## Version Strategies | ||
| 41 | 104 | ||||
| @@ -44,54 +107,48 @@ Gordon automatically: | |||||
| 44 | Always deploy the most recent build: | 107 | Always deploy the most recent build: | ||
| 45 | 108 | ||||
| 46 | ```bash | 109 | ```bash | ||
| 47 | - | docker tag myapp registry.mydomain.com/myapp:latest | 110 | + | docker tag myapp gordon.example.com/myapp:latest |
| 48 | - | docker push registry.mydomain.com/myapp:latest | 111 | + | docker push gordon.example.com/myapp:latest |
| 49 | ``` | 112 | ``` | ||
| 50 | 113 | ||||
| 51 | - | Configure route: | |||
| 52 | ```toml | 114 | ```toml | ||
| 53 | [routes] | 115 | [routes] | ||
| 54 | - | "app.mydomain.com" = "myapp:latest" | 116 | + | "app.example.com" = "myapp:latest" |
| 55 | ``` | 117 | ``` | ||
| 56 | 118 | ||||
| 57 | ### Semantic Versioning | 119 | ### Semantic Versioning | ||
| 58 | 120 | ||||
| 59 | - | Pin to specific versions: | 121 | + | Pin routes to specific versions and update config to roll forward: |
| 60 | 122 | ||||
| 61 | ```bash | 123 | ```bash | ||
| 62 | - | docker tag myapp registry.mydomain.com/myapp:v2.1.0 | 124 | + | docker tag myapp gordon.example.com/myapp:v2.1.0 |
| 63 | - | docker push registry.mydomain.com/myapp:v2.1.0 | 125 | + | docker push gordon.example.com/myapp:v2.1.0 |
| 64 | ``` | 126 | ``` | ||
| 65 | 127 | ||||
| 66 | - | Configure route: | |||
| 67 | ```toml | 128 | ```toml | ||
| 68 | [routes] | 129 | [routes] | ||
| 69 | - | "app.mydomain.com" = "myapp:v2.1.0" | 130 | + | "app.example.com" = "myapp:v2.1.0" |
| 70 | ``` | 131 | ``` | ||
| 71 | 132 | ||||
| 72 | - | Update config to deploy new version: | 133 | + | To deploy a new version, update the tag in `gordon.toml` and push the new image. |
| 73 | - | ```toml | |||
| 74 | - | [routes] | |||
| 75 | - | "app.mydomain.com" = "myapp:v2.2.0" | |||
| 76 | - | ``` | |||
| 77 | 134 | ||||
| 78 | ### Git SHA Tags | 135 | ### Git SHA Tags | ||
| 79 | 136 | ||||
| 80 | - | Tag with commit hash for traceability: | 137 | + | Tag with commit hash for full traceability: |
| 81 | 138 | ||||
| 82 | ```bash | 139 | ```bash | ||
| 83 | VERSION=$(git rev-parse --short HEAD) | 140 | VERSION=$(git rev-parse --short HEAD) | ||
| 84 | - | docker tag myapp registry.mydomain.com/myapp:$VERSION | 141 | + | docker tag myapp gordon.example.com/myapp:$VERSION |
| 85 | - | docker push registry.mydomain.com/myapp:$VERSION | 142 | + | docker push gordon.example.com/myapp:$VERSION |
| 86 | ``` | 143 | ``` | ||
| 87 | 144 | ||||
| 88 | ## Zero-Downtime Deployment | 145 | ## Zero-Downtime Deployment | ||
| 89 | 146 | ||||
| 90 | Gordon performs zero-downtime deployments by default: | 147 | Gordon performs zero-downtime deployments by default: | ||
| 91 | 148 | ||||
| 92 | - | 1. **New container starts** while old is still running | 149 | + | 1. **New container starts** while the old one is still running |
| 93 | - | 2. **Health check** waits for new container readiness | 150 | + | 2. **Health check** waits for the new container to become ready |
| 94 | - | 3. **Traffic switches** to new container | 151 | + | 3. **Traffic switches** to the new container |
| 95 | 4. **Old container stops** after traffic moves | 152 | 4. **Old container stops** after traffic moves | ||
| 96 | 153 | ||||
| 97 | ``` | 154 | ``` | ||
| @@ -103,83 +160,12 @@ New Container: [══════════════════ | |||||
| 103 | ↑ start ↑ traffic routed | 160 | ↑ start ↑ traffic routed | ||
| 104 | ``` | 161 | ``` | ||
| 105 | 162 | ||||
| 106 | - | ## Environment-Specific Deployments | |||
| 107 | - | ||||
| 108 | - | ### Development | |||
| 109 | - | ||||
| 110 | - | ```toml | |||
| 111 | - | [routes] | |||
| 112 | - | "dev.mydomain.com" = "myapp:latest" | |||
| 113 | - | ``` | |||
| 114 | - | ||||
| 115 | - | ```bash | |||
| 116 | - | docker push registry.mydomain.com/myapp:latest | |||
| 117 | - | ``` | |||
| 118 | - | ||||
| 119 | - | ### Staging | |||
| 120 | - | ||||
| 121 | - | ```toml | |||
| 122 | - | [routes] | |||
| 123 | - | "staging.mydomain.com" = "myapp:staging" | |||
| 124 | - | ``` | |||
| 125 | - | ||||
| 126 | - | ```bash | |||
| 127 | - | docker tag myapp registry.mydomain.com/myapp:staging | |||
| 128 | - | docker push registry.mydomain.com/myapp:staging | |||
| 129 | - | ``` | |||
| 130 | - | ||||
| 131 | - | ### Production | |||
| 132 | - | ||||
| 133 | - | ```toml | |||
| 134 | - | [routes] | |||
| 135 | - | "app.mydomain.com" = "myapp:v2.1.0" | |||
| 136 | - | ``` | |||
| 137 | - | ||||
| 138 | - | ```bash | |||
| 139 | - | docker tag myapp registry.mydomain.com/myapp:v2.1.0 | |||
| 140 | - | docker push registry.mydomain.com/myapp:v2.1.0 | |||
| 141 | - | # Then update gordon.toml and reload | |||
| 142 | - | ``` | |||
| 143 | - | ||||
| 144 | - | ## Deployment Checklist | |||
| 145 | - | ||||
| 146 | - | Before deploying: | |||
| 147 | - | ||||
| 148 | - | - [ ] Build passes locally | |||
| 149 | - | - [ ] Tests pass | |||
| 150 | - | - [ ] Environment file configured (`~/.gordon/env/app_mydomain_com.env`) | |||
| 151 | - | - [ ] DNS pointing to Gordon server | |||
| 152 | - | - [ ] Route configured in `gordon.toml` | |||
| 153 | - | ||||
| 154 | - | After deploying: | |||
| 155 | - | ||||
| 156 | - | - [ ] Container starts successfully | |||
| 157 | - | - [ ] Application responds to requests | |||
| 158 | - | - [ ] Logs show no errors | |||
| 159 | - | - [ ] Health checks pass | |||
| 160 | - | ||||
| 161 | - | ## Monitoring Deployments | |||
| 162 | - | ||||
| 163 | - | ### Watch Logs | |||
| 164 | - | ||||
| 165 | - | ```bash | |||
| 166 | - | gordon logs -f | |||
| 167 | - | ``` | |||
| 168 | - | ||||
| 169 | - | ### Check Container Status | |||
| 170 | - | ||||
| 171 | - | ```bash | |||
| 172 | - | docker ps | grep gordon | |||
| 173 | - | ``` | |||
| 174 | - | ||||
| 175 | - | ### Verify Routing | |||
| 176 | - | ||||
| 177 | - | ```bash | |||
| 178 | - | curl -I https://app.mydomain.com | |||
| 179 | - | ``` | |||
| 180 | - | ||||
| 181 | ## Related | 163 | ## Related | ||
| 182 | 164 | ||||
| 183 | - [GitHub Actions](./github-actions.md) | 165 | - [GitHub Actions](./github-actions.md) | ||
| 166 | + | - [GitLab CI](./gitlab-ci.md) | |||
| 167 | + | - [Generic CI](./generic-ci.md) | |||
| 184 | - [Rollback](./rollback.md) | 168 | - [Rollback](./rollback.md) | ||
| 185 | - [Routes Configuration](../config/routes.md) | 169 | - [Routes Configuration](../config/routes.md) | ||
| 170 | + | - [Authentication](../config/auth.md) | |||
| 171 | + | - [Auto-Route](../config/auto-route.md) | |||
M docs/index.md +3 -1
| @@ -60,8 +60,10 @@ Gordon runs on your VPS and provides: | |||
| 60 | 60 | ||
| 61 | 61 | ### Deployment | |
| 62 | 62 | ||
| 63 | - | - [Deployment Overview](./deployment/index.md) - Deployment strategies | |
| 63 | + | - [Deployment Overview](./deployment/index.md) - Deployment strategies and methods | |
| 64 | 64 | - [GitHub Actions](./deployment/github-actions.md) - CI/CD with GitHub | |
| 65 | + | - [GitLab CI](./deployment/gitlab-ci.md) - CI/CD with GitLab | |
| 66 | + | - [Generic CI](./deployment/generic-ci.md) - Jenkins, CircleCI, Drone, and others | |
| 65 | 67 | - [Rollback](./deployment/rollback.md) - Version management and rollback | |
| 66 | 68 | ||
| 67 | 69 | ### Reference | |
| @@ -60,8 +60,10 @@ Gordon runs on your VPS and provides: | |||||
| 60 | 60 | ||||
| 61 | ### Deployment | 61 | ### Deployment | ||
| 62 | 62 | ||||
| 63 | - | - [Deployment Overview](./deployment/index.md) - Deployment strategies | 63 | + | - [Deployment Overview](./deployment/index.md) - Deployment strategies and methods |
| 64 | - [GitHub Actions](./deployment/github-actions.md) - CI/CD with GitHub | 64 | - [GitHub Actions](./deployment/github-actions.md) - CI/CD with GitHub | ||
| 65 | + | - [GitLab CI](./deployment/gitlab-ci.md) - CI/CD with GitLab | |||
| 66 | + | - [Generic CI](./deployment/generic-ci.md) - Jenkins, CircleCI, Drone, and others | |||
| 65 | - [Rollback](./deployment/rollback.md) - Version management and rollback | 67 | - [Rollback](./deployment/rollback.md) - Version management and rollback | ||
| 66 | 68 | ||||
| 67 | ### Reference | 69 | ### Reference | ||