Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6c8b7d0
Remove ORAS manifest delete from merge workflow
ianpittwood May 29, 2026
3e43189
feat: add ImageTarget.temp_tag_name for stable temp refs
ianpittwood May 29, 2026
2dfa62e
refactor: align temp_tag_name test with file style, trim docstring
ianpittwood May 29, 2026
4fd5116
feat: add index_only mode to OrasMergeWorkflow
ianpittwood May 29, 2026
d23635e
fix: guard index_only merge against missing temp_registry
ianpittwood May 29, 2026
c216937
feat: thread index_only through OrasPlugin.execute
ianpittwood May 29, 2026
26a390d
feat: add --index-only to bakery ci merge
ianpittwood May 29, 2026
58e0c73
refactor: hoist test imports and panel the --index-only option
ianpittwood May 29, 2026
02804ef
feat: add bakery ci summary command for CI job summaries
ianpittwood May 29, 2026
ec0a2e5
refactor: use enum for ci summary --mode, validate context, hoist import
ianpittwood May 29, 2026
959fc89
feat: add temp_tagged setting and --temp-tagged build flag
ianpittwood May 29, 2026
7f2fdb6
feat: push tagged multi-arch temp ref when temp_tagged is set
ianpittwood May 29, 2026
314a2bb
test: tidy temp_tagged bake test (hoist imports, explicit fixture path)
ianpittwood May 29, 2026
109362a
feat: tri-state push (off/temp/on) in bakery-build-native workflow
ianpittwood May 29, 2026
5f149d3
feat: tri-state push (off/temp/on) in bakery-build emulation workflow
ianpittwood May 29, 2026
88bf91e
feat: publish temp multi-arch artifacts for same-repo PRs in bakery-b…
ianpittwood May 29, 2026
c3e9064
fix: keep fork PR cache behavior unchanged in bakery-build-pr
ianpittwood May 29, 2026
a59edd8
TEMP: retarget setup-bakery + version default to feat/dry-run-artifacts
ianpittwood May 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 49 additions & 16 deletions .github/workflows/bakery-build-native.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ on:
inputs:
version:
description: "The version of the Posit Bakery tool to install"
default: "main"
default: "feat/dry-run-artifacts"
required: false
type: string
context:
Expand Down Expand Up @@ -38,10 +38,10 @@ on:
required: false
type: string
push:
description: "Whether to push images to registries [default: false]"
default: false
description: "Push target [default: off] [options: off (no push), temp (multi-arch index to temp registry only), on (push to final registries)]"
default: "off"
required: false
type: boolean
type: string
retry:
description: "Number of times to retry a failed build [default: 1]"
default: 1
Expand Down Expand Up @@ -109,8 +109,17 @@ jobs:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Validate push input
env:
PUSH: ${{ inputs.push }}
run: |
case "$PUSH" in
off|temp|on) ;;
*) echo "::error::Invalid push value '$PUSH'; expected off, temp, or on." ; exit 1 ;;
esac

- name: Install
uses: "posit-dev/images-shared/setup-bakery@main"
uses: "posit-dev/images-shared/setup-bakery@feat/dry-run-artifacts"
with:
version: ${{ inputs.version }}

Expand Down Expand Up @@ -147,7 +156,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup bakery
uses: "posit-dev/images-shared/setup-bakery@main"
uses: "posit-dev/images-shared/setup-bakery@feat/dry-run-artifacts"
with:
version: ${{ inputs.version }}

Expand Down Expand Up @@ -188,22 +197,22 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

- name: Login to Docker Hub
if: ${{ inputs.push && steps.filter-steps.outputs.docker-hub == 'true' }}
if: ${{ inputs.push == 'on' && steps.filter-steps.outputs.docker-hub == 'true' }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: "posit"
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

- name: Configure AWS Credentials
if: ${{ inputs.push && steps.filter-steps.outputs.ecr == 'true' }}
if: ${{ inputs.push == 'on' && steps.filter-steps.outputs.ecr == 'true' }}
uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1
with:
role-to-assume: ${{ secrets.AWS_ROLE }}
aws-region: ${{ inputs.aws-region }}
role-session-name: gha-bakery-build

- name: Login to Amazon ECR
if: ${{ inputs.push && steps.filter-steps.outputs.ecr == 'true' }}
if: ${{ inputs.push == 'on' && steps.filter-steps.outputs.ecr == 'true' }}
uses: aws-actions/amazon-ecr-login@fa648b43de3d4d023bcb3f89ed6940096949c419 # v2.1.5

- name: Normalize platform
Expand Down Expand Up @@ -287,7 +296,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup bakery
uses: "posit-dev/images-shared/setup-bakery@main"
uses: "posit-dev/images-shared/setup-bakery@feat/dry-run-artifacts"
with:
version: ${{ inputs.version }}

Expand Down Expand Up @@ -320,22 +329,22 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}

- name: Login to Docker Hub
if: ${{ inputs.push && steps.filter-steps.outputs.docker-hub == 'true' }}
if: ${{ inputs.push == 'on' && steps.filter-steps.outputs.docker-hub == 'true' }}
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: "posit"
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

- name: Configure AWS Credentials
if: ${{ inputs.push && steps.filter-steps.outputs.ecr == 'true' }}
if: ${{ inputs.push == 'on' && steps.filter-steps.outputs.ecr == 'true' }}
uses: aws-actions/configure-aws-credentials@d979d5b3a71173a29b74b5b88418bfda9437d885 # v6.1.1
with:
role-to-assume: ${{ secrets.AWS_ROLE }}
aws-region: ${{ inputs.aws-region }}
role-session-name: gha-bakery-build

- name: Login to Amazon ECR
if: ${{ inputs.push && steps.filter-steps.outputs.ecr == 'true' }}
if: ${{ inputs.push == 'on' && steps.filter-steps.outputs.ecr == 'true' }}
uses: aws-actions/amazon-ecr-login@fa648b43de3d4d023bcb3f89ed6940096949c419 # v2.1.5

- name: Setup docker buildx
Expand All @@ -361,18 +370,42 @@ jobs:
REGISTRY: ghcr.io/${{ github.repository_owner }}
PUSH: ${{ inputs.push }}
run: |
if [ "$PUSH" = "true" ]; then PUSH_FLAG=""; else PUSH_FLAG="--dry-run"; fi
case "$PUSH" in
on) PUSH_FLAG="" ;;
temp) PUSH_FLAG="--index-only" ;;
*) PUSH_FLAG="--dry-run" ;;
esac
bakery ci merge \
--context "$CONTEXT" \
--temp-registry "$REGISTRY" \
$PUSH_FLAG \
./*-metadata.json

- name: Build Artifact Summary
if: ${{ inputs.push != 'off' }}
env:
CONTEXT: ${{ inputs.context }}
REGISTRY: ghcr.io/${{ github.repository_owner }}
PUSH: ${{ inputs.push }}
DEV_VERSIONS: ${{ inputs.dev-versions }}
MATRIX_VERSIONS: ${{ inputs.matrix-versions }}
IMAGE_VERSION: ${{ inputs.image-version }}
DEV_STREAM: ${{ inputs.dev-stream }}
run: |
IMAGE_VERSION="${IMAGE_VERSION#v}"
if [ "$PUSH" = "on" ]; then MODE="final"; else MODE="temp"; fi
ARGS=(--mode "$MODE" --temp-registry "$REGISTRY" --context "$CONTEXT"
--dev-versions "$DEV_VERSIONS" --matrix-versions "$MATRIX_VERSIONS")
[[ -n "$IMAGE_VERSION" ]] && ARGS+=(--image-version "$IMAGE_VERSION")
[[ -n "$DEV_STREAM" ]] && ARGS+=(--dev-stream "$DEV_STREAM")
bakery ci summary "${ARGS[@]}" --output summary.md
cat summary.md >> "$GITHUB_STEP_SUMMARY"

readme:
name: Push READMEs
permissions:
contents: read
if: ${{ inputs.push }}
if: ${{ inputs.push == 'on' }}
needs:
- merge
runs-on: ubuntu-latest
Expand All @@ -382,7 +415,7 @@ jobs:
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup bakery
uses: "posit-dev/images-shared/setup-bakery@main"
uses: "posit-dev/images-shared/setup-bakery@feat/dry-run-artifacts"
with:
version: ${{ inputs.version }}

Expand Down
161 changes: 138 additions & 23 deletions .github/workflows/bakery-build-pr.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
# Fork-safe PR build workflow for Posit container images.
#
# Unlike bakery-build-native.yml this workflow never pushes images.
# Fork PRs get a read-only GITHUB_TOKEN with no access to repo secrets,
# so registry logins and caching are conditional on the PR source.
# Fork PRs stay load-only and never push: they get a read-only GITHUB_TOKEN
# with no access to repo secrets, so registry logins and caching are skipped.
# Same-repo PRs push a temporary multi-arch index to ghcr.io/<owner> (by
# digest per-platform, then assembled with `bakery ci merge --index-only`) so
# maintainers can pull and debug the built image when tests fail. PRs never
# push to the final/release registries.
#
# Registry logins and caching are conditional on the PR source.
#
# Security policy: No ${{ }} expressions in `run:` blocks.
# All expression values are assigned to `env:` and referenced as
Expand All @@ -17,7 +22,7 @@
inputs:
version:
description: "Bakery version to install"
default: "main"
default: "feat/dry-run-artifacts"
required: false
type: string
context:
Expand Down Expand Up @@ -92,7 +97,7 @@
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install
uses: "posit-dev/images-shared/setup-bakery@main"
uses: "posit-dev/images-shared/setup-bakery@feat/dry-run-artifacts"
with:
version: ${{ inputs.version }}

Expand Down Expand Up @@ -141,7 +146,7 @@
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup bakery
uses: "posit-dev/images-shared/setup-bakery@main"
uses: "posit-dev/images-shared/setup-bakery@feat/dry-run-artifacts"
with:
version: ${{ inputs.version }}

Expand Down Expand Up @@ -191,41 +196,151 @@
DEV_VERSIONS: ${{ inputs.dev-versions }}
MATRIX_VERSIONS: ${{ inputs.matrix-versions }}
BAKERY_CONTEXT: ${{ inputs.context }}
REGISTRY_OWNER: ${{ github.repository_owner }}
REGISTRY: ghcr.io/${{ github.repository_owner }}
NORMALIZED_PLATFORM: ${{ steps.normalize-platform.outputs.platform }}
CACHE: ${{ inputs.cache }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Cache only for same-repo PRs when enabled; fork PRs have no
# registry credentials, so they never receive cache flags.
CACHE_FLAGS=()
if [ "$IS_FORK" != "true" ] && [ "$CACHE" = "true" ]; then
CACHE_FLAGS=(--cache-registry "ghcr.io/${REGISTRY_OWNER}")
CACHE_FLAGS=(--cache-registry "$REGISTRY")
fi
if [ "$IS_FORK" = "true" ]; then
bakery build \
--strategy build --pull --load \
--retry "$RETRY" \
--image-name "^${IMAGE_NAME}$" \
--image-version "$IMAGE_VERSION" \
--image-platform "$IMAGE_PLATFORM" \
--dev-versions "$DEV_VERSIONS" \
--matrix-versions "$MATRIX_VERSIONS" \
"${CACHE_FLAGS[@]}" \
--context "$BAKERY_CONTEXT"
else
bakery build \
--strategy build --pull --push \
--retry "$RETRY" \
--image-name "^${IMAGE_NAME}$" \
--image-version "$IMAGE_VERSION" \
--image-platform "$IMAGE_PLATFORM" \
--dev-versions "$DEV_VERSIONS" \
--matrix-versions "$MATRIX_VERSIONS" \
"${CACHE_FLAGS[@]}" \
--temp-registry "$REGISTRY" \
--metadata-file "./${IMAGE_NAME}-${IMAGE_VERSION}-${NORMALIZED_PLATFORM}-metadata.json" \
--context "$BAKERY_CONTEXT"
fi
bakery build \
--strategy build --pull --load \
--retry "$RETRY" \
--image-name "^${IMAGE_NAME}$" \
--image-version "$IMAGE_VERSION" \
--image-platform "$IMAGE_PLATFORM" \
--dev-versions "$DEV_VERSIONS" \
--matrix-versions "$MATRIX_VERSIONS" \
"${CACHE_FLAGS[@]}" \
--context "$BAKERY_CONTEXT"

- name: Test
env:
IS_FORK: ${{ needs.detect.outputs.is-fork }}
IMAGE_NAME: ${{ matrix.img.image }}
IMAGE_VERSION: ${{ matrix.img.version }}
IMAGE_PLATFORM: ${{ matrix.img.platform }}
DEV_VERSIONS: ${{ inputs.dev-versions }}
MATRIX_VERSIONS: ${{ inputs.matrix-versions }}
NORMALIZED_PLATFORM: ${{ steps.normalize-platform.outputs.platform }}
BAKERY_CONTEXT: ${{ inputs.context }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DGOSS_ARGS=(
--image-name "^${IMAGE_NAME}$"
--image-version "$IMAGE_VERSION"
--image-platform "$IMAGE_PLATFORM"
--dev-versions "$DEV_VERSIONS"
--matrix-versions "$MATRIX_VERSIONS"
--context "$BAKERY_CONTEXT"
)
if [ "$IS_FORK" != "true" ]; then
# Same-repo PRs pushed by digest; resolve via the build metadata.
DGOSS_ARGS+=(--metadata-file "./${IMAGE_NAME}-${IMAGE_VERSION}-${NORMALIZED_PLATFORM}-metadata.json")
fi
GOSS_PATH=${GITHUB_WORKSPACE}/tools/goss \
DGOSS_PATH=${GITHUB_WORKSPACE}/tools/dgoss \
bakery run dgoss \
--image-name "^${IMAGE_NAME}$" \
--image-version "$IMAGE_VERSION" \
--image-platform "$IMAGE_PLATFORM" \
bakery run dgoss "${DGOSS_ARGS[@]}"

- name: Upload Metadata
if: needs.detect.outputs.is-fork != 'true'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: "${{ matrix.img.image }}-${{ matrix.img.version }}-${{ steps.normalize-platform.outputs.platform }}-metadata"
path: "./${{ matrix.img.image }}-${{ matrix.img.version }}-${{ steps.normalize-platform.outputs.platform }}-metadata.json"
overwrite: 'true'

merge:
name: "Merge (temp index)"
if: ${{ needs.detect.outputs.is-fork != 'true' }}
permissions:
contents: read
packages: write
needs:
- detect
- build-test
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

Check notice

Code scanning / zizmor

credential persistence through GitHub Actions artifacts: does not set persist-credentials: false Note

credential persistence through GitHub Actions artifacts: does not set persist-credentials: false
Comment on lines +284 to +285

- name: Setup bakery
uses: "posit-dev/images-shared/setup-bakery@feat/dry-run-artifacts"
with:
version: ${{ inputs.version }}

- name: Set up Docker
uses: docker/setup-docker-action@b2189fbf2a6592b51fee7cdd93ee2bfaeba733db # v5.1.0
with:
daemon-config: |
{
"features": {
"containerd-snapshotter": true
}
}

- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Setup docker buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0

- name: Setup ORAS CLI
uses: oras-project/setup-oras@38de303aac69abb66f3e6255b7198bff35f323e3 # v2.0.0

- name: Download Metadata
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
pattern: "*-metadata"
merge-multiple: true

- name: Merge index (temp)
env:
BAKERY_CONTEXT: ${{ inputs.context }}
REGISTRY_OWNER: ${{ github.repository_owner }}
run: |
bakery ci merge \
--context "$BAKERY_CONTEXT" \
--temp-registry "ghcr.io/${REGISTRY_OWNER}" \
--index-only \
./*-metadata.json

- name: Build Artifact Summary
env:
BAKERY_CONTEXT: ${{ inputs.context }}
REGISTRY_OWNER: ${{ github.repository_owner }}
DEV_VERSIONS: ${{ inputs.dev-versions }}
MATRIX_VERSIONS: ${{ inputs.matrix-versions }}
run: |
bakery ci summary \
--mode temp \
--temp-registry "ghcr.io/${REGISTRY_OWNER}" \
--context "$BAKERY_CONTEXT" \
--dev-versions "$DEV_VERSIONS" \
--matrix-versions "$MATRIX_VERSIONS" \
--context "$BAKERY_CONTEXT"
--output summary.md
cat summary.md >> "$GITHUB_STEP_SUMMARY"
Loading
Loading