v2.31.1 f37fe67

github-actions.md RawHistoryFolder

GitHub Actions Deployment

Two approaches for deploying with GitHub Actions: the gordon push CLI (recommended) or a Docker-based workflow using Gordon's official action.

Prerequisites

  1. Gordon server running with registry authentication enabled
  2. Deployment token generated with the required scopes
  3. GitHub repository secrets configured

Use the gordon push CLI for a lightweight, single-step build and deploy.

1. Generate Token

On your Gordon server:

gordon auth token generate \
  --subject github-actions \
  --scopes "push,pull,admin:routes:read,admin:config:write" \
  --expiry 0

Save the token output.

2. Add GitHub Secrets

In your repository: Settings → Secrets → Actions → New repository secret

Secret Value
GORDON_TOKEN The generated token
GORDON_REMOTE https://gordon.example.com

3. Setup Gordon CLI

Add this step to your workflow to install the Gordon binary:

- name: Setup Gordon
  uses: bnema/gordon/.github/actions/setup-gordon@main
  # with:
  #   version: latest  # default, or pin to e.g. v2.0.0

4. Workflow Examples

Deploy on Tag Push

Gordon auto-detects the version from $GITHUB_REF (e.g., refs/tags/v1.2.0 → v1.2.0).

name: Deploy to Gordon

on:
  push:
    tags: ['v*']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Gordon
        uses: bnema/gordon/.github/actions/setup-gordon@main

      - name: Build and Deploy
        env:
          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
        run: |
          gordon push --build \
            --remote ${{ secrets.GORDON_REMOTE }} \
            --no-confirm

Continuous Deploy on Main

Deploy on every push to main. The version defaults to latest or the output of git describe.

name: Deploy to Gordon

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Gordon
        uses: bnema/gordon/.github/actions/setup-gordon@main

      - name: Build and Deploy
        env:
          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
        run: |
          gordon push --build \
            --remote ${{ secrets.GORDON_REMOTE }} \
            --tag latest \
            --no-confirm

Manual Dispatch

Allow manual deployments with an optional tag input:

name: Deploy to Gordon

on:
  workflow_dispatch:
    inputs:
      tag:
        description: 'Tag to deploy (leave empty to use git describe)'
        required: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.tag || github.ref }}
          fetch-depth: 0

      - name: Setup Gordon
        uses: bnema/gordon/.github/actions/setup-gordon@main

      - name: Build and Deploy
        env:
          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
          GORDON_REMOTE: ${{ secrets.GORDON_REMOTE }}
          DEPLOY_TAG: ${{ inputs.tag }}
        run: |
          args=(push --build --remote "$GORDON_REMOTE" --no-confirm)
          if [[ -n "$DEPLOY_TAG" ]]; then
            [[ "$DEPLOY_TAG" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ ]] || exit 1
            args+=(--tag "$DEPLOY_TAG")
          fi
          gordon "${args[@]}"

Monorepo

Deploy multiple services with separate gordon push calls:

name: Deploy Services

on:
  push:
    tags: ['v*']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Gordon
        uses: bnema/gordon/.github/actions/setup-gordon@main

      - name: Deploy API
        env:
          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
        run: |
          gordon push --build \
            --remote ${{ secrets.GORDON_REMOTE }} \
            --file ./services/api/Dockerfile \
            myapp-api \
            --no-confirm

      - name: Deploy Web
        env:
          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
        run: |
          gordon push --build \
            --remote ${{ secrets.GORDON_REMOTE }} \
            --file ./services/web/Dockerfile \
            myapp-web \
            --no-confirm

With Build Args

Pass build arguments to the Docker build:

- name: Build and Deploy
  env:
    GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
  run: |
    gordon push --build \
      --remote ${{ secrets.GORDON_REMOTE }} \
      --build-arg NODE_ENV=production \
      --build-arg API_URL=https://api.example.com \
      --build-arg BUILD_DATE=${{ github.event.head_commit.timestamp }} \
      --no-confirm

setup-gordon Action Reference

Input Required Default Description
version No latest Gordon version to install (v2.0.0 or latest)
Output Description
version The version actually installed
path Path to the installed binary

Alternative: Docker-based Workflow

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.

Setup

Add these secrets to your repository:

Secret Value
GORDON_REGISTRY registry.gordon.example.com
GORDON_USERNAME github-actions
GORDON_TOKEN The generated token

Workflow

name: Deploy to Gordon

on:
  push:
    tags: ['v*']

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Login to Gordon Registry
        run: echo "${{ secrets.GORDON_TOKEN }}" | docker login ${{ secrets.GORDON_REGISTRY }} -u ${{ secrets.GORDON_USERNAME }} --password-stdin

      - name: Build and Push
        run: |
          docker build -t ${{ secrets.GORDON_REGISTRY }}/myapp:${{ github.ref_name }} .
          docker push ${{ secrets.GORDON_REGISTRY }}/myapp:${{ github.ref_name }}

Alternative: Gordon GitHub Action

Use the official bnema/gordon action for a fully declarative workflow. This action handles login, build, and push in a single step.

Setup

Requires the same 3 secrets as the Docker-based workflow: GORDON_REGISTRY, GORDON_USERNAME, GORDON_TOKEN.

Workflow Examples

Deploy on Tag Push

name: Deploy to Gordon

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Gordon
        uses: bnema/gordon/.github/actions/deploy@main
        with:
          registry: ${{ secrets.GORDON_REGISTRY }}
          username: ${{ secrets.GORDON_USERNAME }}
          password: ${{ secrets.GORDON_TOKEN }}

Continuous Deployment

Deploy on every push to main:

name: Deploy to Gordon

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Gordon
        uses: bnema/gordon/.github/actions/deploy@main
        with:
          registry: ${{ secrets.GORDON_REGISTRY }}
          username: ${{ secrets.GORDON_USERNAME }}
          password: ${{ secrets.GORDON_TOKEN }}
          push-latest: 'true'

Manual Deployment

Allow manual deployments with a custom tag:

name: Deploy to Gordon

on:
  workflow_dispatch:
    inputs:
      tag:
        description: 'Tag to deploy'
        required: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.inputs.tag || github.ref }}

      - name: Deploy to Gordon
        uses: bnema/gordon/.github/actions/deploy@main
        with:
          registry: ${{ secrets.GORDON_REGISTRY }}
          username: ${{ secrets.GORDON_USERNAME }}
          password: ${{ secrets.GORDON_TOKEN }}
          tag: ${{ github.event.inputs.tag }}

Monorepo Deployment

Deploy multiple services:

name: Deploy Services

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy-api:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: bnema/gordon/.github/actions/deploy@main
        with:
          registry: ${{ secrets.GORDON_REGISTRY }}
          username: ${{ secrets.GORDON_USERNAME }}
          password: ${{ secrets.GORDON_TOKEN }}
          image: myapp-api
          dockerfile: ./services/api/Dockerfile
          context: ./services/api

  deploy-web:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: bnema/gordon/.github/actions/deploy@main
        with:
          registry: ${{ secrets.GORDON_REGISTRY }}
          username: ${{ secrets.GORDON_USERNAME }}
          password: ${{ secrets.GORDON_TOKEN }}
          image: myapp-web
          dockerfile: ./services/web/Dockerfile
          context: ./services/web

With Build Arguments

- uses: bnema/gordon/.github/actions/deploy@main
  with:
    registry: ${{ secrets.GORDON_REGISTRY }}
    username: ${{ secrets.GORDON_USERNAME }}
    password: ${{ secrets.GORDON_TOKEN }}
    build-args: |
      NODE_ENV=production
      API_URL=https://api.example.com
      BUILD_DATE=${{ github.event.head_commit.timestamp }}

Multi-Platform Build

- uses: bnema/gordon/.github/actions/deploy@main
  with:
    registry: ${{ secrets.GORDON_REGISTRY }}
    username: ${{ secrets.GORDON_USERNAME }}
    password: ${{ secrets.GORDON_TOKEN }}
    platforms: linux/amd64,linux/arm64

Action Reference

Inputs

Input Required Default Description
registry Yes - Gordon registry URL
username Yes - Registry username
password Yes - Registry token
image No repo name Image name
tag No git tag/SHA Image tag
dockerfile No ./Dockerfile Dockerfile path
context No . Build context
push-latest No false Also push :latest tag
platforms No linux/amd64 Target platforms
build-args No - Build arguments

Outputs

Output Description
image Full image name
tag Image tag

Deployment Summary

Add a deployment summary to your workflow:

- name: Deploy to Gordon
  id: deploy
  uses: bnema/gordon/.github/actions/deploy@main
  with:
    registry: ${{ secrets.GORDON_REGISTRY }}
    username: ${{ secrets.GORDON_USERNAME }}
    password: ${{ secrets.GORDON_TOKEN }}

- name: Deployment Summary
  run: |
    echo "## Deployment Complete" >> $GITHUB_STEP_SUMMARY
    echo "" >> $GITHUB_STEP_SUMMARY
    echo "**Image:** \`${{ steps.deploy.outputs.image }}\`" >> $GITHUB_STEP_SUMMARY
    echo "**Tag:** \`${{ steps.deploy.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY

Troubleshooting

Authentication Failed

Error: unauthorized: authentication required

Solution: Verify secrets are correctly set and token has push scope.

Image Not Found After Push

Solution: Ensure Gordon config has a route for the pushed image.

Build Fails

Solution: Check Dockerfile path and build context settings.

source
1# GitHub Actions Deployment
2
3Two approaches for deploying with GitHub Actions: the `gordon push` CLI (recommended) or a Docker-based workflow using Gordon's official action.
4
5## Prerequisites
6
71. Gordon server running with registry authentication enabled
82. Deployment token generated with the required scopes
93. GitHub repository secrets configured
10
11## Recommended: gordon push
12
13Use the `gordon push` CLI for a lightweight, single-step build and deploy.
14
15### 1. Generate Token
16
17On your Gordon server:
18
19```bash
20gordon auth token generate \
21  --subject github-actions \
22  --scopes "push,pull,admin:routes:read,admin:config:write" \
23  --expiry 0
24```
25
26Save the token output.
27
28### 2. Add GitHub Secrets
29
30In your repository: Settings → Secrets → Actions → New repository secret
31
32| Secret | Value |
33|--------|-------|
34| `GORDON_TOKEN` | The generated token |
35| `GORDON_REMOTE` | `https://gordon.example.com` |
36
37### 3. Setup Gordon CLI
38
39Add this step to your workflow to install the Gordon binary:
40
41```yaml
42- name: Setup Gordon
43  uses: bnema/gordon/.github/actions/setup-gordon@main
44  # with:
45  #   version: latest  # default, or pin to e.g. v2.0.0
46```
47
48### 4. Workflow Examples
49
50#### Deploy on Tag Push
51
52Gordon auto-detects the version from `$GITHUB_REF` (e.g., `refs/tags/v1.2.0` → `v1.2.0`).
53
54```yaml
55name: Deploy to Gordon
56
57on:
58  push:
59    tags: ['v*']
60
61jobs:
62  deploy:
63    runs-on: ubuntu-latest
64    steps:
65      - uses: actions/checkout@v4
66
67      - name: Setup Gordon
68        uses: bnema/gordon/.github/actions/setup-gordon@main
69
70      - name: Build and Deploy
71        env:
72          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
73        run: |
74          gordon push --build \
75            --remote ${{ secrets.GORDON_REMOTE }} \
76            --no-confirm
77```
78
79#### Continuous Deploy on Main
80
81Deploy on every push to main. The version defaults to `latest` or the output of `git describe`.
82
83```yaml
84name: Deploy to Gordon
85
86on:
87  push:
88    branches:
89      - main
90
91jobs:
92  deploy:
93    runs-on: ubuntu-latest
94    steps:
95      - uses: actions/checkout@v4
96        with:
97          fetch-depth: 0
98
99      - name: Setup Gordon
100        uses: bnema/gordon/.github/actions/setup-gordon@main
101
102      - name: Build and Deploy
103        env:
104          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
105        run: |
106          gordon push --build \
107            --remote ${{ secrets.GORDON_REMOTE }} \
108            --tag latest \
109            --no-confirm
110```
111
112#### Manual Dispatch
113
114Allow manual deployments with an optional tag input:
115
116```yaml
117name: Deploy to Gordon
118
119on:
120  workflow_dispatch:
121    inputs:
122      tag:
123        description: 'Tag to deploy (leave empty to use git describe)'
124        required: false
125
126jobs:
127  deploy:
128    runs-on: ubuntu-latest
129    steps:
130      - uses: actions/checkout@v4
131        with:
132          ref: ${{ github.event.inputs.tag || github.ref }}
133          fetch-depth: 0
134
135      - name: Setup Gordon
136        uses: bnema/gordon/.github/actions/setup-gordon@main
137
138      - name: Build and Deploy
139        env:
140          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
141          GORDON_REMOTE: ${{ secrets.GORDON_REMOTE }}
142          DEPLOY_TAG: ${{ inputs.tag }}
143        run: |
144          args=(push --build --remote "$GORDON_REMOTE" --no-confirm)
145          if [[ -n "$DEPLOY_TAG" ]]; then
146            [[ "$DEPLOY_TAG" =~ ^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$ ]] || exit 1
147            args+=(--tag "$DEPLOY_TAG")
148          fi
149          gordon "${args[@]}"
150```
151
152#### Monorepo
153
154Deploy multiple services with separate `gordon push` calls:
155
156```yaml
157name: Deploy Services
158
159on:
160  push:
161    tags: ['v*']
162
163jobs:
164  deploy:
165    runs-on: ubuntu-latest
166    steps:
167      - uses: actions/checkout@v4
168
169      - name: Setup Gordon
170        uses: bnema/gordon/.github/actions/setup-gordon@main
171
172      - name: Deploy API
173        env:
174          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
175        run: |
176          gordon push --build \
177            --remote ${{ secrets.GORDON_REMOTE }} \
178            --file ./services/api/Dockerfile \
179            myapp-api \
180            --no-confirm
181
182      - name: Deploy Web
183        env:
184          GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
185        run: |
186          gordon push --build \
187            --remote ${{ secrets.GORDON_REMOTE }} \
188            --file ./services/web/Dockerfile \
189            myapp-web \
190            --no-confirm
191```
192
193#### With Build Args
194
195Pass build arguments to the Docker build:
196
197```yaml
198- name: Build and Deploy
199  env:
200    GORDON_TOKEN: ${{ secrets.GORDON_TOKEN }}
201  run: |
202    gordon push --build \
203      --remote ${{ secrets.GORDON_REMOTE }} \
204      --build-arg NODE_ENV=production \
205      --build-arg API_URL=https://api.example.com \
206      --build-arg BUILD_DATE=${{ github.event.head_commit.timestamp }} \
207      --no-confirm
208```
209
210### setup-gordon Action Reference
211
212| Input | Required | Default | Description |
213|-------|----------|---------|-------------|
214| `version` | No | `latest` | Gordon version to install (`v2.0.0` or `latest`) |
215
216| Output | Description |
217|--------|-------------|
218| `version` | The version actually installed |
219| `path` | Path to the installed binary |
220
221## Alternative: Docker-based Workflow
222
223For 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.
224
225### Setup
226
227Add these secrets to your repository:
228
229| Secret | Value |
230|--------|-------|
231| `GORDON_REGISTRY` | `registry.gordon.example.com` |
232| `GORDON_USERNAME` | `github-actions` |
233| `GORDON_TOKEN` | The generated token |
234
235### Workflow
236
237```yaml
238name: Deploy to Gordon
239
240on:
241  push:
242    tags: ['v*']
243
244jobs:
245  deploy:
246    runs-on: ubuntu-latest
247    steps:
248      - uses: actions/checkout@v4
249
250      - name: Login to Gordon Registry
251        run: echo "${{ secrets.GORDON_TOKEN }}" | docker login ${{ secrets.GORDON_REGISTRY }} -u ${{ secrets.GORDON_USERNAME }} --password-stdin
252
253      - name: Build and Push
254        run: |
255          docker build -t ${{ secrets.GORDON_REGISTRY }}/myapp:${{ github.ref_name }} .
256          docker push ${{ secrets.GORDON_REGISTRY }}/myapp:${{ github.ref_name }}
257```
258
259## Alternative: Gordon GitHub Action
260
261Use the official `bnema/gordon` action for a fully declarative workflow. This action handles login, build, and push in a single step.
262
263### Setup
264
265Requires the same 3 secrets as the Docker-based workflow: `GORDON_REGISTRY`, `GORDON_USERNAME`, `GORDON_TOKEN`.
266
267### Workflow Examples
268
269#### Deploy on Tag Push
270
271```yaml
272name: Deploy to Gordon
273
274on:
275  push:
276    tags:
277      - 'v*'
278
279jobs:
280  deploy:
281    runs-on: ubuntu-latest
282    steps:
283      - uses: actions/checkout@v4
284
285      - name: Deploy to Gordon
286        uses: bnema/gordon/.github/actions/deploy@main
287        with:
288          registry: ${{ secrets.GORDON_REGISTRY }}
289          username: ${{ secrets.GORDON_USERNAME }}
290          password: ${{ secrets.GORDON_TOKEN }}
291```
292
293#### Continuous Deployment
294
295Deploy on every push to main:
296
297```yaml
298name: Deploy to Gordon
299
300on:
301  push:
302    branches:
303      - main
304
305jobs:
306  deploy:
307    runs-on: ubuntu-latest
308    steps:
309      - uses: actions/checkout@v4
310
311      - name: Deploy to Gordon
312        uses: bnema/gordon/.github/actions/deploy@main
313        with:
314          registry: ${{ secrets.GORDON_REGISTRY }}
315          username: ${{ secrets.GORDON_USERNAME }}
316          password: ${{ secrets.GORDON_TOKEN }}
317          push-latest: 'true'
318```
319
320#### Manual Deployment
321
322Allow manual deployments with a custom tag:
323
324```yaml
325name: Deploy to Gordon
326
327on:
328  workflow_dispatch:
329    inputs:
330      tag:
331        description: 'Tag to deploy'
332        required: false
333
334jobs:
335  deploy:
336    runs-on: ubuntu-latest
337    steps:
338      - uses: actions/checkout@v4
339        with:
340          ref: ${{ github.event.inputs.tag || github.ref }}
341
342      - name: Deploy to Gordon
343        uses: bnema/gordon/.github/actions/deploy@main
344        with:
345          registry: ${{ secrets.GORDON_REGISTRY }}
346          username: ${{ secrets.GORDON_USERNAME }}
347          password: ${{ secrets.GORDON_TOKEN }}
348          tag: ${{ github.event.inputs.tag }}
349```
350
351#### Monorepo Deployment
352
353Deploy multiple services:
354
355```yaml
356name: Deploy Services
357
358on:
359  push:
360    tags:
361      - 'v*'
362
363jobs:
364  deploy-api:
365    runs-on: ubuntu-latest
366    steps:
367      - uses: actions/checkout@v4
368      - uses: bnema/gordon/.github/actions/deploy@main
369        with:
370          registry: ${{ secrets.GORDON_REGISTRY }}
371          username: ${{ secrets.GORDON_USERNAME }}
372          password: ${{ secrets.GORDON_TOKEN }}
373          image: myapp-api
374          dockerfile: ./services/api/Dockerfile
375          context: ./services/api
376
377  deploy-web:
378    runs-on: ubuntu-latest
379    steps:
380      - uses: actions/checkout@v4
381      - uses: bnema/gordon/.github/actions/deploy@main
382        with:
383          registry: ${{ secrets.GORDON_REGISTRY }}
384          username: ${{ secrets.GORDON_USERNAME }}
385          password: ${{ secrets.GORDON_TOKEN }}
386          image: myapp-web
387          dockerfile: ./services/web/Dockerfile
388          context: ./services/web
389```
390
391#### With Build Arguments
392
393```yaml
394- uses: bnema/gordon/.github/actions/deploy@main
395  with:
396    registry: ${{ secrets.GORDON_REGISTRY }}
397    username: ${{ secrets.GORDON_USERNAME }}
398    password: ${{ secrets.GORDON_TOKEN }}
399    build-args: |
400      NODE_ENV=production
401      API_URL=https://api.example.com
402      BUILD_DATE=${{ github.event.head_commit.timestamp }}
403```
404
405#### Multi-Platform Build
406
407```yaml
408- uses: bnema/gordon/.github/actions/deploy@main
409  with:
410    registry: ${{ secrets.GORDON_REGISTRY }}
411    username: ${{ secrets.GORDON_USERNAME }}
412    password: ${{ secrets.GORDON_TOKEN }}
413    platforms: linux/amd64,linux/arm64
414```
415
416### Action Reference
417
418#### Inputs
419
420| Input | Required | Default | Description |
421|-------|----------|---------|-------------|
422| `registry` | Yes | - | Gordon registry URL |
423| `username` | Yes | - | Registry username |
424| `password` | Yes | - | Registry token |
425| `image` | No | repo name | Image name |
426| `tag` | No | git tag/SHA | Image tag |
427| `dockerfile` | No | `./Dockerfile` | Dockerfile path |
428| `context` | No | `.` | Build context |
429| `push-latest` | No | `false` | Also push :latest tag |
430| `platforms` | No | `linux/amd64` | Target platforms |
431| `build-args` | No | - | Build arguments |
432
433#### Outputs
434
435| Output | Description |
436|--------|-------------|
437| `image` | Full image name |
438| `tag` | Image tag |
439
440#### Deployment Summary
441
442Add a deployment summary to your workflow:
443
444```yaml
445- name: Deploy to Gordon
446  id: deploy
447  uses: bnema/gordon/.github/actions/deploy@main
448  with:
449    registry: ${{ secrets.GORDON_REGISTRY }}
450    username: ${{ secrets.GORDON_USERNAME }}
451    password: ${{ secrets.GORDON_TOKEN }}
452
453- name: Deployment Summary
454  run: |
455    echo "## Deployment Complete" >> $GITHUB_STEP_SUMMARY
456    echo "" >> $GITHUB_STEP_SUMMARY
457    echo "**Image:** \`${{ steps.deploy.outputs.image }}\`" >> $GITHUB_STEP_SUMMARY
458    echo "**Tag:** \`${{ steps.deploy.outputs.tag }}\`" >> $GITHUB_STEP_SUMMARY
459```
460
461## Troubleshooting
462
463### Authentication Failed
464
465```
466Error: unauthorized: authentication required
467```
468
469**Solution:** Verify secrets are correctly set and token has `push` scope.
470
471### Image Not Found After Push
472
473**Solution:** Ensure Gordon config has a route for the pushed image.
474
475### Build Fails
476
477**Solution:** Check Dockerfile path and build context settings.
478
479## Related
480
481- [GitLab CI](./gitlab-ci.md)
482- [Generic CI](./generic-ci.md)
483- [Deployment Overview](./index.md)
484- [Authentication](../config/auth.md)
485- [Push Command](../cli/push.md)
486- [Rollback](./rollback.md)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close