Skip to content

Commit ad546ea

Browse files
committed
ci: wire GitHub Pages and nightly image builds
- publish docs with docs.deva.sh domain metadata and site links - share tool version resolution across nightly and tagged releases
1 parent a69ce81 commit ad546ea

9 files changed

Lines changed: 326 additions & 40 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
name: Nightly Images
2+
3+
on:
4+
schedule:
5+
- cron: "17 4 * * *"
6+
workflow_dispatch:
7+
8+
env:
9+
REGISTRY: ghcr.io
10+
IMAGE_NAME: thevibeworks/deva
11+
12+
permissions:
13+
contents: read
14+
packages: write
15+
16+
concurrency:
17+
group: nightly-images
18+
cancel-in-progress: true
19+
20+
jobs:
21+
resolve-versions:
22+
name: Resolve Latest Tool Versions
23+
runs-on: ubuntu-latest
24+
outputs:
25+
stamp: ${{ steps.versions.outputs.stamp }}
26+
claude_code_version: ${{ steps.versions.outputs.claude_code_version }}
27+
codex_version: ${{ steps.versions.outputs.codex_version }}
28+
gemini_cli_version: ${{ steps.versions.outputs.gemini_cli_version }}
29+
atlas_cli_version: ${{ steps.versions.outputs.atlas_cli_version }}
30+
copilot_api_version: ${{ steps.versions.outputs.copilot_api_version }}
31+
steps:
32+
- name: Checkout
33+
uses: actions/checkout@v4
34+
35+
- name: Setup Node
36+
uses: actions/setup-node@v4
37+
with:
38+
node-version: "22"
39+
40+
- name: Resolve versions
41+
id: versions
42+
shell: bash
43+
env:
44+
GH_TOKEN: ${{ github.token }}
45+
run: bash ./scripts/resolve-tool-versions.sh
46+
47+
- name: Summary
48+
run: |
49+
cat <<EOF >> "$GITHUB_STEP_SUMMARY"
50+
## Nightly Tool Versions
51+
52+
- Claude Code: \`${{ steps.versions.outputs.claude_code_version }}\`
53+
- Codex: \`${{ steps.versions.outputs.codex_version }}\`
54+
- Gemini CLI: \`${{ steps.versions.outputs.gemini_cli_version }}\`
55+
- Atlas CLI: \`${{ steps.versions.outputs.atlas_cli_version }}\`
56+
- Copilot API: \`${{ steps.versions.outputs.copilot_api_version }}\`
57+
- Stamp: \`${{ steps.versions.outputs.stamp }}\`
58+
EOF
59+
60+
build-base:
61+
name: Build Nightly Base Image
62+
needs: resolve-versions
63+
runs-on: ubuntu-latest
64+
steps:
65+
- name: Checkout
66+
uses: actions/checkout@v4
67+
68+
- name: Set up QEMU
69+
uses: docker/setup-qemu-action@v3
70+
71+
- name: Set up Docker Buildx
72+
uses: docker/setup-buildx-action@v3
73+
74+
- name: Log in to Container Registry
75+
uses: docker/login-action@v3
76+
with:
77+
registry: ${{ env.REGISTRY }}
78+
username: ${{ github.actor }}
79+
password: ${{ secrets.GITHUB_TOKEN }}
80+
81+
- name: Extract metadata
82+
id: meta
83+
uses: docker/metadata-action@v5
84+
with:
85+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
86+
tags: |
87+
type=raw,value=nightly
88+
type=raw,value=nightly-${{ needs.resolve-versions.outputs.stamp }}
89+
labels: |
90+
org.opencontainers.image.title=deva-nightly
91+
org.opencontainers.image.description=Nightly deva image with latest upstream CLI versions
92+
93+
- name: Build and push base image
94+
uses: docker/build-push-action@v5
95+
with:
96+
context: .
97+
file: ./Dockerfile
98+
platforms: linux/amd64,linux/arm64
99+
push: true
100+
tags: ${{ steps.meta.outputs.tags }}
101+
labels: ${{ steps.meta.outputs.labels }}
102+
cache-from: type=gha,scope=nightly-base
103+
cache-to: type=gha,mode=max,scope=nightly-base
104+
build-args: |
105+
CLAUDE_CODE_VERSION=${{ needs.resolve-versions.outputs.claude_code_version }}
106+
CODEX_VERSION=${{ needs.resolve-versions.outputs.codex_version }}
107+
GEMINI_CLI_VERSION=${{ needs.resolve-versions.outputs.gemini_cli_version }}
108+
ATLAS_CLI_VERSION=${{ needs.resolve-versions.outputs.atlas_cli_version }}
109+
COPILOT_API_VERSION=${{ needs.resolve-versions.outputs.copilot_api_version }}
110+
111+
build-rust:
112+
name: Build Nightly Rust Image
113+
needs: [resolve-versions, build-base]
114+
runs-on: ubuntu-latest
115+
steps:
116+
- name: Checkout
117+
uses: actions/checkout@v4
118+
119+
- name: Set up QEMU
120+
uses: docker/setup-qemu-action@v3
121+
122+
- name: Set up Docker Buildx
123+
uses: docker/setup-buildx-action@v3
124+
125+
- name: Log in to Container Registry
126+
uses: docker/login-action@v3
127+
with:
128+
registry: ${{ env.REGISTRY }}
129+
username: ${{ github.actor }}
130+
password: ${{ secrets.GITHUB_TOKEN }}
131+
132+
- name: Extract metadata
133+
id: meta
134+
uses: docker/metadata-action@v5
135+
with:
136+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
137+
tags: |
138+
type=raw,value=nightly-rust
139+
type=raw,value=nightly-${{ needs.resolve-versions.outputs.stamp }}-rust
140+
labels: |
141+
org.opencontainers.image.title=deva-nightly-rust
142+
org.opencontainers.image.description=Nightly deva rust image with latest upstream CLI versions
143+
144+
- name: Build and push rust image
145+
uses: docker/build-push-action@v5
146+
with:
147+
context: .
148+
file: ./Dockerfile.rust
149+
platforms: linux/amd64,linux/arm64
150+
push: true
151+
tags: ${{ steps.meta.outputs.tags }}
152+
labels: ${{ steps.meta.outputs.labels }}
153+
cache-from: type=gha,scope=nightly-rust
154+
cache-to: type=gha,mode=max,scope=nightly-rust
155+
build-args: |
156+
BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:nightly-${{ needs.resolve-versions.outputs.stamp }}
157+
158+
summary:
159+
name: Nightly Summary
160+
needs: [resolve-versions, build-base, build-rust]
161+
runs-on: ubuntu-latest
162+
steps:
163+
- name: Publish summary
164+
run: |
165+
cat <<EOF >> "$GITHUB_STEP_SUMMARY"
166+
## Published Nightly Images
167+
168+
- \`ghcr.io/thevibeworks/deva:nightly\`
169+
- \`ghcr.io/thevibeworks/deva:nightly-${{ needs.resolve-versions.outputs.stamp }}\`
170+
- \`ghcr.io/thevibeworks/deva:nightly-rust\`
171+
- \`ghcr.io/thevibeworks/deva:nightly-${{ needs.resolve-versions.outputs.stamp }}-rust\`
172+
173+
This workflow refreshes nightly image tags only.
174+
Semver releases and GitHub Releases remain manual.
175+
EOF

.github/workflows/pages.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ jobs:
3838
- name: Build site
3939
run: mkdocs build --strict
4040

41+
- name: Set docs domain marker
42+
run: printf 'docs.deva.sh\n' > site/CNAME
43+
4144
- name: Remove unpublished artifacts
4245
run: rm -rf site/devlog
4346

.github/workflows/release.yml

Lines changed: 83 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,73 @@ env:
1616
IMAGE_NAME: thevibeworks/deva
1717

1818
jobs:
19+
prepare:
20+
name: Prepare Release Metadata
21+
runs-on: ubuntu-latest
22+
outputs:
23+
release_tag: ${{ steps.release.outputs.release_tag }}
24+
steps:
25+
- name: Resolve release tag
26+
id: release
27+
shell: bash
28+
run: |
29+
set -euo pipefail
30+
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
31+
release_tag="${{ github.event.inputs.tag }}"
32+
else
33+
release_tag="${GITHUB_REF#refs/tags/}"
34+
fi
35+
[ -n "$release_tag" ] || { echo "error: empty release tag" >&2; exit 1; }
36+
echo "release_tag=$release_tag" >> "$GITHUB_OUTPUT"
37+
38+
resolve-versions:
39+
name: Resolve Tool Versions
40+
runs-on: ubuntu-latest
41+
outputs:
42+
claude_code_version: ${{ steps.versions.outputs.claude_code_version }}
43+
codex_version: ${{ steps.versions.outputs.codex_version }}
44+
gemini_cli_version: ${{ steps.versions.outputs.gemini_cli_version }}
45+
atlas_cli_version: ${{ steps.versions.outputs.atlas_cli_version }}
46+
copilot_api_version: ${{ steps.versions.outputs.copilot_api_version }}
47+
steps:
48+
- name: Checkout
49+
uses: actions/checkout@v4
50+
51+
- name: Setup Node
52+
uses: actions/setup-node@v4
53+
with:
54+
node-version: "22"
55+
56+
- name: Resolve versions
57+
id: versions
58+
env:
59+
GH_TOKEN: ${{ github.token }}
60+
run: bash ./scripts/resolve-tool-versions.sh
61+
62+
- name: Summary
63+
run: |
64+
cat <<EOF >> "$GITHUB_STEP_SUMMARY"
65+
## Release Tool Versions
66+
67+
- Claude Code: \`${{ steps.versions.outputs.claude_code_version }}\`
68+
- Codex: \`${{ steps.versions.outputs.codex_version }}\`
69+
- Gemini CLI: \`${{ steps.versions.outputs.gemini_cli_version }}\`
70+
- Atlas CLI: \`${{ steps.versions.outputs.atlas_cli_version }}\`
71+
- Copilot API: \`${{ steps.versions.outputs.copilot_api_version }}\`
72+
EOF
73+
1974
build-and-push:
2075
name: Build and Push Docker Image
76+
needs: [prepare, resolve-versions]
2177
runs-on: ubuntu-latest
2278
permissions:
2379
contents: read
2480
packages: write
2581
steps:
2682
- name: Checkout
2783
uses: actions/checkout@v4
84+
with:
85+
ref: ${{ needs.prepare.outputs.release_tag }}
2886

2987
- name: Set up QEMU
3088
uses: docker/setup-qemu-action@v3
@@ -45,8 +103,8 @@ jobs:
45103
with:
46104
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
47105
tags: |
48-
type=ref,event=tag
49-
type=raw,value=latest,enable={{is_default_branch}}
106+
type=raw,value=${{ needs.prepare.outputs.release_tag }}
107+
type=raw,value=latest
50108
51109
- name: Build and push base image
52110
uses: docker/build-push-action@v5
@@ -59,17 +117,25 @@ jobs:
59117
labels: ${{ steps.meta.outputs.labels }}
60118
cache-from: type=gha
61119
cache-to: type=gha,mode=max
120+
build-args: |
121+
CLAUDE_CODE_VERSION=${{ needs.resolve-versions.outputs.claude_code_version }}
122+
CODEX_VERSION=${{ needs.resolve-versions.outputs.codex_version }}
123+
GEMINI_CLI_VERSION=${{ needs.resolve-versions.outputs.gemini_cli_version }}
124+
ATLAS_CLI_VERSION=${{ needs.resolve-versions.outputs.atlas_cli_version }}
125+
COPILOT_API_VERSION=${{ needs.resolve-versions.outputs.copilot_api_version }}
62126
63127
build-and-push-rust:
64128
name: Build and Push Rust Profile Image
65129
runs-on: ubuntu-latest
66-
needs: build-and-push
130+
needs: [prepare, build-and-push]
67131
permissions:
68132
contents: read
69133
packages: write
70134
steps:
71135
- name: Checkout
72136
uses: actions/checkout@v4
137+
with:
138+
ref: ${{ needs.prepare.outputs.release_tag }}
73139

74140
- name: Set up QEMU
75141
uses: docker/setup-qemu-action@v3
@@ -90,8 +156,8 @@ jobs:
90156
with:
91157
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
92158
tags: |
93-
type=ref,event=tag,suffix=-rust
94-
type=raw,value=rust,enable={{is_default_branch}}
159+
type=raw,value=${{ needs.prepare.outputs.release_tag }}-rust
160+
type=raw,value=rust
95161
96162
- name: Build and push rust image
97163
uses: docker/build-push-action@v5
@@ -105,51 +171,33 @@ jobs:
105171
cache-from: type=gha
106172
cache-to: type=gha,mode=max
107173
build-args: |
108-
BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
174+
BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.prepare.outputs.release_tag }}
109175
110176
release:
111177
name: Create GitHub Release
112178
runs-on: ubuntu-latest
113-
needs: [build-and-push, build-and-push-rust]
179+
needs: [prepare, build-and-push, build-and-push-rust]
114180
permissions:
115181
contents: write
116182
steps:
117183
- name: Checkout
118184
uses: actions/checkout@v4
119185
with:
186+
ref: ${{ needs.prepare.outputs.release_tag }}
120187
fetch-depth: 0
121188

122-
- name: Get version from tag
123-
id: version
124-
run: |
125-
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
126-
echo "version=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
127-
else
128-
echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
129-
fi
130-
131-
- name: Update version in deva.sh
132-
run: |
133-
VERSION="${{ steps.version.outputs.version }}"
134-
# Remove 'v' prefix if present
135-
VERSION=${VERSION#v}
136-
sed -i "s/^VERSION=.*/VERSION=\"$VERSION\"/" deva.sh
137-
git config --local user.email "action@github.com"
138-
git config --local user.name "GitHub Action"
139-
git add deva.sh
140-
git commit -m "Update version to $VERSION" || echo "No changes to commit"
141-
142189
- name: Generate release notes
143190
id: release_notes
191+
shell: bash
144192
run: |
145-
# Get the previous tag
146-
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "")
193+
set -euo pipefail
194+
RELEASE_TAG="${{ needs.prepare.outputs.release_tag }}"
195+
PREVIOUS_TAG="$(git tag --sort=-version:refname | grep -Fxv "$RELEASE_TAG" | head -1 || true)"
147196
148-
# Generate release notes
149197
if [ -n "$PREVIOUS_TAG" ]; then
150198
echo "## Changes since $PREVIOUS_TAG" > release_notes.md
151199
echo "" >> release_notes.md
152-
git log --pretty=format:"- %s (%h)" $PREVIOUS_TAG..HEAD >> release_notes.md
200+
git log --pretty=format:"- %s (%h)" "$PREVIOUS_TAG..$RELEASE_TAG" >> release_notes.md
153201
else
154202
echo "## Initial Release" > release_notes.md
155203
echo "" >> release_notes.md
@@ -160,11 +208,11 @@ jobs:
160208
echo "## Docker Images" >> release_notes.md
161209
echo "" >> release_notes.md
162210
echo "**Base Profile (Python, Node, Go):**" >> release_notes.md
163-
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}\`" >> release_notes.md
211+
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:$RELEASE_TAG\`" >> release_notes.md
164212
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:latest\`" >> release_notes.md
165213
echo "" >> release_notes.md
166214
echo "**Rust Profile (includes Rust toolchain):**" >> release_notes.md
167-
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}-rust\`" >> release_notes.md
215+
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:${RELEASE_TAG}-rust\`" >> release_notes.md
168216
echo "- \`ghcr.io/${{ env.IMAGE_NAME }}:rust\`" >> release_notes.md
169217
echo "" >> release_notes.md
170218
echo "## Supported Architectures" >> release_notes.md
@@ -175,8 +223,8 @@ jobs:
175223
- name: Create Release
176224
uses: softprops/action-gh-release@v1
177225
with:
178-
tag_name: ${{ steps.version.outputs.version }}
179-
name: Release ${{ steps.version.outputs.version }}
226+
tag_name: ${{ needs.prepare.outputs.release_tag }}
227+
name: Release ${{ needs.prepare.outputs.release_tag }}
180228
body_path: release_notes.md
181229
generate_release_notes: true
182230
append_body: true

0 commit comments

Comments
 (0)