Add CI workflows for dual-image channel pattern
All checks were successful
Build Non-Prod Image / build-and-release (push) Successful in 29s
Build Prod Image / build-and-release (push) Successful in 32s

- Non-prod workflow: builds on push to main, pushes to acme-nonprod registry, creates Octopus release in Non-Prod channel
- Prod workflow: builds on v* tags, pushes to acme-prod registry, creates Octopus release in Prod channel
- Simple Alpine Dockerfile for demo purposes
This commit is contained in:
octopus.oreillyit.nz
2026-03-23 16:47:00 +13:00
parent f9b62d05b8
commit 3e09802db8
4 changed files with 142 additions and 2 deletions

View File

@@ -0,0 +1,62 @@
name: Build Non-Prod Image
on:
push:
branches: [main]
env:
REGISTRY: gitea.oreillyit.nz
IMAGE: acme-nonprod/demo-app
OCTOPUS_SERVER: https://taniwha.octopus.app
OCTOPUS_SPACE_ID: Spaces-102
OCTOPUS_PROJECT_ID: Projects-101
OCTOPUS_CHANNEL_ID: Channels-124
jobs:
build-and-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate version
id: version
run: echo "sha=sha-${GITHUB_SHA::8}" >> "$GITHUB_OUTPUT"
- name: Login to registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push
run: |
docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.version.outputs.sha }} .
docker push ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.version.outputs.sha }}
- name: Create Octopus Release
run: |
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
-H "X-Octopus-ApiKey: ${{ secrets.OCTOPUS_API_KEY }}" \
-H "Content-Type: application/json" \
"${{ env.OCTOPUS_SERVER }}/api/${{ env.OCTOPUS_SPACE_ID }}/releases" \
-d '{
"ProjectId": "${{ env.OCTOPUS_PROJECT_ID }}",
"ChannelId": "${{ env.OCTOPUS_CHANNEL_ID }}",
"Version": "${{ steps.version.outputs.sha }}",
"SelectedPackages": [
{
"ActionName": "Deploy Non-Prod Image",
"PackageReferenceName": "demo-app",
"Version": "${{ steps.version.outputs.sha }}"
}
]
}')
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
echo "Response: $BODY"
if [ "$HTTP_CODE" -ge 400 ]; then
echo "::error::Failed to create release (HTTP $HTTP_CODE)"
exit 1
fi
echo "Release created successfully"

View File

@@ -0,0 +1,62 @@
name: Build Prod Image
on:
push:
tags: ['v*']
env:
REGISTRY: gitea.oreillyit.nz
IMAGE: acme-prod/demo-app
OCTOPUS_SERVER: https://taniwha.octopus.app
OCTOPUS_SPACE_ID: Spaces-102
OCTOPUS_PROJECT_ID: Projects-101
OCTOPUS_CHANNEL_ID: Channels-125
jobs:
build-and-release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Generate version
id: version
run: echo "sha=sha-${GITHUB_SHA::8}" >> "$GITHUB_OUTPUT"
- name: Login to registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Build and push
run: |
docker build -t ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.version.outputs.sha }} .
docker push ${{ env.REGISTRY }}/${{ env.IMAGE }}:${{ steps.version.outputs.sha }}
- name: Create Octopus Release
run: |
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST \
-H "X-Octopus-ApiKey: ${{ secrets.OCTOPUS_API_KEY }}" \
-H "Content-Type: application/json" \
"${{ env.OCTOPUS_SERVER }}/api/${{ env.OCTOPUS_SPACE_ID }}/releases" \
-d '{
"ProjectId": "${{ env.OCTOPUS_PROJECT_ID }}",
"ChannelId": "${{ env.OCTOPUS_CHANNEL_ID }}",
"Version": "prod-${{ steps.version.outputs.sha }}",
"SelectedPackages": [
{
"ActionName": "Deploy Prod Image",
"PackageReferenceName": "demo-app",
"Version": "${{ steps.version.outputs.sha }}"
}
]
}')
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | sed '$d')
echo "Response: $BODY"
if [ "$HTTP_CODE" -ge 400 ]; then
echo "::error::Failed to create release (HTTP $HTTP_CODE)"
exit 1
fi
echo "Release created successfully"

3
Dockerfile Normal file
View File

@@ -0,0 +1,3 @@
FROM alpine:3.21
LABEL org.opencontainers.image.source="https://gitea.oreillyit.nz/octopus.oreillyit.nz/demo-app"
CMD ["echo", "Hello from demo-app"]

View File

@@ -1,3 +1,16 @@
# demo-app
# Demo App — Dual Image Channel Pattern
Demo app for dual-image channel pattern
Demonstrates Octopus Deploy's channel pattern for routing non-prod and prod container images through separate lifecycles.
## How it works
- **Push to `main`** → builds non-prod image → pushes to `acme-nonprod/demo-app` → creates Octopus release in Non-Prod channel
- **Push a `v*` tag** → builds prod image → pushes to `acme-prod/demo-app` → creates Octopus release in Prod channel
Each channel has its own lifecycle:
- Non-Prod: Development → Staging (cannot reach Production)
- Prod: Staging → Production
## Octopus Space
https://taniwha.octopus.app/app#/Spaces-102