Skip to content

Commit f0302ad

Browse files
authored
Merge pull request #20 from link-assistant/issue-17-eb0edbddcdb5
ci: publish release container to GitHub Packages
2 parents 00720e1 + 8ebdf86 commit f0302ad

4 files changed

Lines changed: 126 additions & 3 deletions

File tree

.github/workflows/release.yml

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ jobs:
247247
runs-on: ubuntu-latest
248248
permissions:
249249
contents: write
250+
packages: write
250251
steps:
251252
- uses: actions/checkout@v4
252253
with:
@@ -292,9 +293,40 @@ jobs:
292293
if: steps.check.outputs.should_release == 'true'
293294
id: publish-crate
294295
env:
295-
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
296+
CARGO_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }}
296297
run: rust-script scripts/publish-crate.rs
297298

299+
- name: Log in to GitHub Container Registry
300+
if: steps.check.outputs.should_release == 'true'
301+
uses: docker/login-action@v3
302+
with:
303+
registry: ghcr.io
304+
username: ${{ github.actor }}
305+
password: ${{ secrets.GITHUB_TOKEN }}
306+
307+
- name: Set up Docker Buildx
308+
if: steps.check.outputs.should_release == 'true'
309+
uses: docker/setup-buildx-action@v3
310+
311+
- name: Extract Docker metadata
312+
if: steps.check.outputs.should_release == 'true'
313+
id: docker-meta
314+
uses: docker/metadata-action@v5
315+
with:
316+
images: ghcr.io/${{ github.repository }}
317+
tags: |
318+
type=raw,value=latest
319+
type=raw,value=${{ steps.current_version.outputs.version }}
320+
321+
- name: Publish Docker image to GitHub Packages
322+
if: steps.check.outputs.should_release == 'true'
323+
uses: docker/build-push-action@v6
324+
with:
325+
context: .
326+
push: true
327+
tags: ${{ steps.docker-meta.outputs.tags }}
328+
labels: ${{ steps.docker-meta.outputs.labels }}
329+
298330
- name: Create GitHub Release
299331
if: steps.check.outputs.should_release == 'true'
300332
env:
@@ -316,6 +348,7 @@ jobs:
316348
runs-on: ubuntu-latest
317349
permissions:
318350
contents: write
351+
packages: write
319352
steps:
320353
- uses: actions/checkout@v4
321354
with:
@@ -349,9 +382,40 @@ jobs:
349382
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
350383
id: publish-crate
351384
env:
352-
CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }}
385+
CARGO_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }}
353386
run: rust-script scripts/publish-crate.rs
354387

388+
- name: Log in to GitHub Container Registry
389+
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
390+
uses: docker/login-action@v3
391+
with:
392+
registry: ghcr.io
393+
username: ${{ github.actor }}
394+
password: ${{ secrets.GITHUB_TOKEN }}
395+
396+
- name: Set up Docker Buildx
397+
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
398+
uses: docker/setup-buildx-action@v3
399+
400+
- name: Extract Docker metadata
401+
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
402+
id: docker-meta
403+
uses: docker/metadata-action@v5
404+
with:
405+
images: ghcr.io/${{ github.repository }}
406+
tags: |
407+
type=raw,value=latest
408+
type=raw,value=${{ steps.version.outputs.new_version }}
409+
410+
- name: Publish Docker image to GitHub Packages
411+
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
412+
uses: docker/build-push-action@v6
413+
with:
414+
context: .
415+
push: true
416+
tags: ${{ steps.docker-meta.outputs.tags }}
417+
labels: ${{ steps.docker-meta.outputs.labels }}
418+
355419
- name: Create GitHub Release
356420
if: steps.version.outputs.version_committed == 'true' || steps.version.outputs.already_released == 'true'
357421
env:

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
bump: patch
3+
---
4+
5+
### Added
6+
- Publish release Docker images to GitHub Container Registry alongside crates.io releases.

scripts/check-release-workflow.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env rust-script
2+
//! Validate release workflow publishing invariants.
3+
4+
use std::fs;
5+
use std::process::exit;
6+
7+
fn main() {
8+
let workflow = fs::read_to_string(".github/workflows/release.yml")
9+
.expect("failed to read .github/workflows/release.yml");
10+
11+
let required_snippets = [
12+
"auto-release:",
13+
"manual-release:",
14+
"packages: write",
15+
"CARGO_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || secrets.CARGO_TOKEN }}",
16+
"docker/login-action@v3",
17+
"docker/setup-buildx-action@v3",
18+
"docker/metadata-action@v5",
19+
"docker/build-push-action@v6",
20+
"ghcr.io/${{ github.repository }}",
21+
"type=raw,value=latest",
22+
"type=raw,value=${{ steps.current_version.outputs.version }}",
23+
"type=raw,value=${{ steps.version.outputs.new_version }}",
24+
];
25+
26+
let mut failures = Vec::new();
27+
for snippet in required_snippets {
28+
if !workflow.contains(snippet) {
29+
failures.push(format!("missing required release workflow snippet: {snippet}"));
30+
}
31+
}
32+
33+
if count_occurrences(&workflow, "packages: write") < 2 {
34+
failures.push("auto and manual release jobs must both grant packages: write".to_string());
35+
}
36+
37+
if count_occurrences(&workflow, "docker/build-push-action@v6") < 2 {
38+
failures.push("auto and manual release jobs must both publish a Docker image".to_string());
39+
}
40+
41+
if failures.is_empty() {
42+
println!("release workflow publishes crates and GHCR images");
43+
} else {
44+
for failure in failures {
45+
eprintln!("Error: {failure}");
46+
}
47+
exit(1);
48+
}
49+
}
50+
51+
fn count_occurrences(haystack: &str, needle: &str) -> usize {
52+
haystack.match_indices(needle).count()
53+
}

0 commit comments

Comments
 (0)