Artifacts Reference
May 6, 2026 · View on GitHub
Complete reference for artifacts.yml configuration format.
For per-ecosystem capability matrices and the artefact-first vs container-first framing, see docs/ecosystems.md.
Overview
The artifacts.yml file defines what to build and where to publish. It consists of two main sections:
artifacts:
- name: my-artifact
# ... artifact configuration
containers:
- name: my-container
from: [my-artifact]
# ... container configuration
Artifacts Section
Artifact Required Fields
Artifact name
- Type:
string - Description: Unique identifier for this artifact
- Used for: Referencing in containers
from:field, artifact upload names - Example:
backend-api,frontend-ui,shared-lib
project-type
- Type:
string - Description: Build system type
- Valid values:
maven,npm,gradle,gradle-android,xcode-ios,cargo,python,go - Example:
project-type: maven
working-directory
- Type:
string - Description: Path to project root (relative to repository root)
- Contains:
pom.xml(Maven),package.json(NPM),build.gradle(Gradle) - Example:
.,services/backend,packages/frontend
Artifact Optional Fields
build-type
- Type:
string - Description: Build type (affects Maven/Gradle behavior)
- Valid values:
application(default),library - Default:
application - Applies to: Maven and Gradle only
- Example:
build-type: library - Behavior:
application: Builds withmvn packagelibrary: Builds withmvn install, generates javadoc and sources JARs
require-authorization
- Type:
boolean - Description: Require user to be in authorized list for releases
- Default:
false - Use case: Production libraries that need release approval
- Example:
require-authorization: true - Requires:
AUTHORIZED_RELEASE_DEVELOPERSsecret set
publish-to
-
Type:
array of strings -
Description: Publishing targets for built artifacts
-
Default:
[github-packages] -
Valid values:
github-packages,maven-central,npmjs,google-play -
Example:
publish-to: - github-packages - maven-central -
Example (Android):
publish-to: - google-play -
Behavior: Workflows only run if target is listed
-
Note: iOS apps use
publish-to: []as they publish via App Store Connect automatically
sboms
- Type:
string(enum / comma-list) - Description: Which CISA SBOM types to generate for this artifact. See docs/sbom.md for the full taxonomy.
- Accepted values:
all— Build + Analyzed-artifact + Analyzed-container (default)none— skip SBOM generation entirelybuild— CISA Build SBOM only (cyclonedx plugin during build)analyzed-artifact— Syft scan of the built binary onlyanalyzed-container— Syft scan of the published container only- Any comma-list of the three layer names, e.g.
build,analyzed-artifact
- Default: Automatic based on project type:
allfor:maven,npm,gradle,gradle-android,cargo,python,gononefor:xcode-ios,meta
- Examples:
# (default — same as omitting the field for a supported project type) sboms: all # Compliance minimum sboms: build # Turn off SBOMs for this artefact sboms: none - Formats produced: SPDX 2.3 and CycloneDX 1.6 (JSON)
- Pipeline cap: The orchestrator
sbomsinput (defaultallon release,noneon release-dev) intersects with this field; the effective set per artefact is the intersection. - What it controls: Release-bundle inclusion, not build-time plugin execution. The language's cyclonedx plugin always runs in the per-stack build workflow with
continue-on-error: true; this field decides whether the resulting BOMs (and syft scans) are included in the release artefact bundle. See docs/sbom.md for the full semantics. - Note:
analyzed-*scans use Syft; ecosystem coverage varies. Thebuildlayer uses the language-native cyclonedx plugin and is the highest-fidelity type.
Configuration Fields (Maven/Gradle)
config.java-version
- Type:
stringornumber - Description: JDK version for Maven/Gradle builds
- Default:
25 - Valid values:
8,11,17,21,25 - Example:
java-version: 25
config.settings-path
- Type:
string - Description: Path to Maven settings.xml (relative to working-directory)
- Default: None (uses default Maven settings)
- Example:
settings-path: .mvn/settings.xml - Use case: Custom Maven repository configuration
Configuration Fields (NPM)
config.node-version
- Type:
stringornumber - Description: Node.js version for NPM builds
- Default:
24 - Valid values:
18,20,22,24 - Example:
node-version: 24
config.npm-tag
- Type:
string - Description: NPM distribution tag for publishing
- Default:
latest - Valid values:
latest,next,beta,alpha - Example:
npm-tag: latest
Configuration Fields (Gradle)
config.gradle-tasks
- Type:
string - Description: Gradle tasks to execute.
gradle(JVM): default isassemble; set to override.gradle-android: not honored on the orchestrator path. The orchestrator (release-build-stage.yml) derives tasks fromproduct-flavor+build-types+include-aaband ignores this field. Configure those instead. The override input still exists onbuild-gradle-android.ymlfor direct callers (e.g., a hand-rolledrelease-dev-workflow.yml).
- Default:
assemble(JVM); derived (Android, ignored) - Example (JVM):
gradle-tasks: build test
config.gradle-version-file
- Type:
string - Description: File containing version properties
- Default:
gradle.properties - Example:
gradle-version-file: gradle.properties
Configuration Fields (Gradle Android)
config.build-module
- Type:
string - Description: Gradle module to build (the application module).
- Required: Yes (for
project-type: gradle-android) - Example:
build-module: app
config.product-flavor
- Type:
string - Description: Product flavor for the build. Combined with
build-typesandinclude-aabto derive the gradle task list (e.g.demo+release+ AAB →assembleDemoRelease bundleDemoRelease). - Default:
""(no flavor) - Example:
product-flavor: demo
config.build-types
- Type:
string - Description: Comma-separated build types to produce.
- Default:
debug,release - Example:
build-types: release
config.include-aab
- Type:
boolean - Description: Also build the Android App Bundle (AAB) for the release build type. Required for Google Play publishing.
- Default:
true - Example:
include-aab: true
config.artifact-name-prefix
- Type:
string - Description: Prefix for derived artifact names when calling
build-gradle-android.ymldirectly. Ignored on the orchestrator path — the orchestrator forwards the artifact'sname:as the upload identifier so it lines up with whatrelease-publish-stage.ymlhands topublish-google-play.yml. - Default:
"" - Example:
artifact-name-prefix: dev
Configuration Fields (Xcode iOS/macOS)
config.xcode-version
- Type:
string - Description: Xcode version to use for building
- Required: Yes
- Valid values:
15.4,16.0,16.1, etc. - Example:
xcode-version: "16.1"
config.scheme
- Type:
string - Description: Xcode scheme to build
- Required: Yes
- Example:
scheme: "Wallet Demo"
config.workspace
- Type:
string - Description: Xcode workspace file (mutually exclusive with
project) - Required: One of
workspaceorproject - Example:
workspace: "MyApp.xcworkspace"
config.project
- Type:
string - Description: Xcode project file (mutually exclusive with
workspace) - Required: One of
workspaceorproject - Example:
project: "MyApp.xcodeproj"
config.configuration
- Type:
string - Description: Build configuration
- Default:
Release - Valid values:
Debug,Release, or custom configurations - Example:
configuration: Release
config.use-xcodegen
- Type:
boolean - Description: Run XcodeGen before version extraction and archive
- Default:
false - Example:
use-xcodegen: true
config.xcodegen-spec
- Type:
string - Description: Path to the XcodeGen spec file, relative to
working-directory - Default:
project.yml - Example:
xcodegen-spec: project.yml - Note: Keep
projectorworkspaceset so later steps use a deterministic build target after generation
config.enable-code-signing
- Type:
boolean - Description: Enable iOS/macOS code signing and IPA export
- Default:
true - Example:
enable-code-signing: true - Requires secrets:
CERTIFICATE_BASE64- Base64-encoded .p12 certificateCERTIFICATE_PASSPHRASE- Certificate passwordPROVISIONING_PROFILE_BASE64- Base64-encoded provisioning profileKEYCHAIN_PASSWORD- Temporary keychain password
config.export-options-var
- Type:
string - Description: Name of GitHub variable containing base64-encoded exportOptions.plist
- Default:
EXPORT_OPTIONS_BASE64 - Example:
export-options-var: EXPORT_OPTIONS_BASE64 - Note: Variable should contain base64-encoded exportOptions.plist for IPA export
config.macos-version
- Type:
string - Description: macOS runner version
- Default:
macos-26 - Valid values:
macos-15,macos-26 - Example:
macos-version: macos-26
config.destination
- Type:
string - Description: Build destination for xcodebuild
- Default:
generic/platform=iOS - Example:
destination: generic/platform=macOS(for macOS apps)
config.submit-for-review
- Type:
boolean - Description: Submit to Apple App Store for review (not just TestFlight)
- Default:
false - Example:
submit-for-review: false(TestFlight only) - Example:
submit-for-review: true(Submit for App Store review) - Note: Use
falsefor beta testing,truefor production releases
config.skip-validation
- Type:
boolean - Description: Skip IPA validation before upload to App Store Connect
- Default:
false - Example:
skip-validation: false(Recommended - validates before upload) - Note: Only set to
trueif validation fails incorrectly
Configuration Fields (Gradle Android - Google Play)
config.enable-android-signing
- Type:
boolean - Description: Enable Android app signing for release builds
- Default:
false - Example:
enable-android-signing: true - Requires secrets:
ANDROID_KEYSTORE- Base64-encoded keystore fileANDROID_KEYSTORE_PASSWORD- Keystore passwordANDROID_KEY_ALIAS- Key aliasANDROID_KEY_PASSWORD- Key password
config.package-name
- Type:
string - Description: Android package name (application ID)
- Required: Yes (for Google Play publishing)
- Example:
package-name: com.example.myapp
config.google-play-track
- Type:
string - Description: Google Play release track
- Default:
internal - Valid values:
internal,alpha,beta,production - Example:
google-play-track: internal
config.google-play-status
- Type:
string - Description: Release status on Google Play
- Default:
completed - Valid values:
completed,inProgress,halted,draft - Example:
google-play-status: completed - Note: Use
inProgresswithuser-fractionfor staged rollouts
config.google-play-user-fraction
- Type:
string - Description: Staged rollout percentage (0.0-1.0)
- Default: Empty (full rollout)
- Example:
google-play-user-fraction: "0.1"(10% rollout) - Note: Only applies when
google-play-status: inProgress
config.google-play-update-priority
- Type:
string - Description: In-app update priority level
- Default:
"0" - Valid values:
"0"to"5"(5 is highest) - Example:
google-play-update-priority: "3"
config.google-play-release-name
- Type:
string - Description: Custom release name (defaults to version from AAB)
- Default: Empty (auto-generated)
- Example:
google-play-release-name: "Summer Update"
config.google-play-changes-not-sent-for-review
- Type:
boolean - Description: Hold changes for manual review in Play Console
- Default:
false - Example:
google-play-changes-not-sent-for-review: true
config.whats-new-directory
- Type:
string - Description: Directory containing localized release notes
- Default: Empty (no release notes)
- Example:
whats-new-directory: distribution/whatsnew - Format: Files named
whatsnew-<LOCALE>(e.g.,whatsnew-en-US,whatsnew-sv-SE)
config.mapping-file
- Type:
string - Description: Path to ProGuard/R8 mapping.txt file
- Default: Empty
- Example:
mapping-file: app/build/outputs/mapping/release/mapping.txt - Use case: De-obfuscate crash reports in Play Console
config.debug-symbols
- Type:
string - Description: Path to native debug symbols (zip or folder)
- Default: Empty
- Example:
debug-symbols: app/build/intermediates/merged_native_libs/release/out/lib - Use case: Symbolicate native crashes in Play Console
Containers Section
Containers reference artifacts via the from: field and are built after all artifacts complete.
Container Required Fields
Container name
- Type:
string - Description: Container image name (becomes part of image tag)
- Example:
backend-api,frontend-ui - Resulting image:
ghcr.io/org/repo/backend-api:v1.0.0 - Single-container collapse: When
nameequals the repo's short name (the common single-container pattern), the redundant<repo>/<repo>subpath is collapsed toghcr.io/org/repo:<tag>. Multi-container layouts where eachnameis distinct from the repo are unaffected.
from
- Type:
array of strings - Description: List of artifact names to include in this container
- Must reference: Existing artifact names from
artifacts[]section - Example:
from: [backend-api](single artifact) - Example:
from: [api, worker, web](multi-artifact container)
container-file
- Type:
string - Description: Path to Containerfile/Dockerfile (relative to repository root)
- Example:
Containerfile,services/backend/Containerfile
Container Optional Fields
context
- Type:
string - Description: Docker build context directory
- Default:
.(repository root) - Example:
context: services/backend
platforms
- Type:
string(comma-separated) - Description: Target CPU architectures. Each platform builds natively on a runner of that architecture (
linux/amd64→ubuntu-24.04,linux/arm64→ubuntu-24.04-arm). No QEMU. Multi-platform inputs split across runners and merge into a single manifest list. - Default:
linux/amd64 - Example:
platforms: linux/amd64,linux/arm64 - Performance: Multi-platform runs in parallel; wall-clock is dominated by the slowest arch leg (≈1.1× single-arch, plus the merge job).
enable-slsa
- Type:
boolean - Description: Generate SLSA provenance attestation
- Default:
true - Requires:
id-token: write,actions: readpermissions - Example:
enable-slsa: true
Container enable-sbom (removed in v3)
The v2.x enable-sbom: bool field on the container block is removed in v3. Container scanning is now derived from each source artefact's sboms field — the container is scanned if any source artefact has analyzed-container in its effective sboms (the default for buildable types). To skip the scan, exclude analyzed-container from the source artefact's sboms (e.g. sboms: build,analyzed-artifact). Hard cutover — the old field is silently ignored.
enable-scan
- Type:
boolean - Description: Run Trivy vulnerability scan
- Default:
true - Requires:
SARIF_UPLOAD_TOKENorg secret for results to appear in Code Scanning - Example:
enable-scan: true
target
- Type:
string - Description: Containerfile stage to build for the runtime image. Useful for multi-stage Containerfiles where the deployable image is not the last stage.
- Default: empty (builds the last stage; current
docker buildbehavior) - Example:
target: runtime - Used by: container-first ecosystems primarily, but the field is generic — any multi-stage Containerfile may set it.
- See also: artefact-first vs container-first framing
extract.binary
Opt-in extraction of compiled binaries as a CI artefact. Used by container-first ecosystems (cargo, future go) where the binary is a byproduct of the container build. The same Containerfile is built a second time with --target set to the extraction stage; the resulting files are uploaded as ${container.name}-binaries.
The extraction shares cache with the runtime image build (same buildkit daemon, same --mount=type=cache IDs), so it does not double-compile.
extract.binary.target
- Type:
string - Description: Containerfile stage that exposes the binaries. Typically
FROM scratch AS export-binarywithCOPY --from=builder ...lines. - Required when
extract.binaryis set. - Example:
target: export-binary
extract.binary.names
- Type: list of
string - Description: Expected binary file basenames in the extracted output. Informational — surfaced in the GitHub Actions step summary and used downstream for naming. Not enforced; if the names don't match the export-binary stage's COPYs, no error is raised.
- Example:
names: [hsm-worker, digg-hsm-keytool]
Full example
containers:
- name: hsm-worker
from: [hsm-worker]
container-file: hsm-worker/Containerfile
context: .
target: runtime
platforms: linux/amd64,linux/arm64
extract:
binary:
target: export-binary
names: [hsm-worker, digg-hsm-keytool]
Output
- GHA artefact
${container.name}-binarieswith per-platform subdirectories (e.g.,linux_amd64/hsm-worker,linux_arm64/hsm-worker). - Aggregated into the GitHub Release alongside SBOMs and other release artefacts when matched by the caller's
release.attachartifactsglob.
build-args
-
Type: key/value object
-
Description: Build arguments for the Containerfile (e.g.,
RUST_VERSION,DEBIAN_VARIANT). The parser converts the object toKEY=VALUElines fordocker/build-push-action, so callers can use the more readable object form inartifacts.yml. -
Example (in artifacts.yml):
containers: - name: my-svc from: [my-svc] container-file: Containerfile context: . build-args: RUST_VERSION: "1.94" DEBIAN_VARIANT: bookworm-slim -
Direct caller equivalent (when invoking
publish-container.ymldirectly, bypassing the orchestrator):uses: diggsweden/reusable-ci/.github/workflows/publish-container.yml@v2.9.0 with: build-args: | RUST_VERSION=1.94 DEBIAN_VARIANT=bookworm-slim
Publishing Targets
github-packages
- Description: GitHub Packages registry
- Requirements:
GITHUB_TOKEN(automatic) - Applies to: Maven, NPM, Gradle
- Registry:
ghcr.io(containers),npm.pkg.github.com(NPM)
maven-central
- Description: Maven Central (Sonatype OSSRH)
- Requirements:
MAVENCENTRAL_USERNAMEsecretMAVENCENTRAL_PASSWORDsecretbuild-type: library(required)
- Applies to: Maven only
- Note: Requires Sonatype account and approved groupId
npmjs
- Description: Public npmjs.org registry
- Requirements:
NPM_TOKENsecret - Applies to: NPM only
- Note: Package must be scoped or publicly available
google-play
- Description: Google Play Store
- Requirements:
GOOGLE_PLAY_SERVICE_ACCOUNT_JSONsecret (service account JSON key)ANDROID_KEYSTORE,ANDROID_KEYSTORE_PASSWORD,ANDROID_KEY_ALIAS,ANDROID_KEY_PASSWORDsecrets (for signing)config.enable-android-signing: trueconfig.package-namespecified
- Applies to: Gradle Android only
- Note: App must already exist in Google Play Console (upload first AAB manually)
Quick Start Examples
Single Artifact (Maven)
.github/artifacts.yml
artifacts:
- name: my-app
project-type: maven
working-directory: .
build-type: application
config:
java-version: 25
.github/workflows/release-workflow.yml
jobs:
release:
uses: diggsweden/reusable-ci/.github/workflows/release-orchestrator.yml@72b9c326139080c9a9c91999ada2d62d19e7ee54 # v2.7.0
with:
reusable-ci-ref: v2.7.0
artifacts-config: .github/artifacts.yml
release-publisher: github-cli
Single Artifact with Container (Maven)
.github/artifacts.yml
artifacts:
- name: my-app
project-type: maven
working-directory: .
build-type: application
config:
java-version: 25
containers:
- name: my-app
from: [my-app]
container-file: Containerfile
context: .
platforms: linux/amd64,linux/arm64
Maven Library (Multiple Targets)
artifacts:
- name: my-lib
project-type: maven
working-directory: library
build-type: library
require-authorization: true
publish-to:
- github-packages
- maven-central
config:
java-version: 25
settings-path: .mvn/settings.xml
NPM Application
artifacts:
- name: my-ui
project-type: npm
working-directory: frontend
config:
node-version: 24
Gradle Android App
artifacts:
- name: my-android-app
project-type: gradle-android
working-directory: .
config:
java-version: 21
build-module: app
product-flavor: demo
build-types: release
gradle-version-file: gradle.properties
Gradle Android App with Google Play Publishing
artifacts:
- name: my-android-app
project-type: gradle-android
working-directory: .
build-type: application
publish-to:
- google-play
config:
java-version: 21
build-module: app
product-flavor: demo
build-types: release
gradle-version-file: gradle.properties
enable-android-signing: true
# Google Play configuration
package-name: com.example.myapp
google-play-track: internal
google-play-status: completed
Required Secrets:
ANDROID_KEYSTORE
ANDROID_KEYSTORE_PASSWORD
ANDROID_KEY_ALIAS
ANDROID_KEY_PASSWORD
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON
iOS/macOS App (Xcode)
artifacts:
- name: my-ios-app
project-type: xcode-ios
working-directory: .
build-type: application
publish-to: [] # iOS apps don't publish to package registries
config:
xcode-version: "16.1"
scheme: "MyApp"
use-xcodegen: true
xcodegen-spec: "project.yml"
project: "MyApp.xcodeproj"
configuration: Release
enable-code-signing: true
export-options-var: EXPORT_OPTIONS_BASE64
macos-version: macos-26
Required Secrets:
CERTIFICATE_BASE64
CERTIFICATE_PASSPHRASE
PROVISIONING_PROFILE_BASE64
KEYCHAIN_PASSWORD
APP_STORE_CONNECT_ISSUER_ID
APP_STORE_CONNECT_API_KEY_ID
APP_STORE_CONNECT_API_PRIVATE_KEY_BASE64
Required Variables:
EXPORT_OPTIONS_BASE64
Encoding certificates/profiles to base64:
# Certificate
base64 -i certificate.p12 -o certificate.txt
# Provisioning Profile
base64 -i profile.mobileprovision -o profile.txt
# Export Options
base64 -i exportOptions.plist -o exportOptions.txt
iOS/macOS App With XcodeGen
artifacts:
- name: my-ios-app
project-type: xcode-ios
working-directory: .
build-type: application
publish-to: []
config:
xcode-version: "16.1"
scheme: "MyApp"
use-xcodegen: true
xcodegen-spec: "project.yml"
project: "MyApp.xcodeproj"
configuration: Release
enable-code-signing: true
export-options-var: EXPORT_OPTIONS_BASE64
macos-version: macos-26
Use project or workspace alongside XcodeGen so version detection and archive steps target the generated Xcode project explicitly.
Multiple iOS Schemes (Demo, Production)
artifacts:
- name: wallet-ios-demo
project-type: xcode-ios
working-directory: .
config:
xcode-version: "16.1"
scheme: "Wallet Demo"
project: "Wallet.xcodeproj"
configuration: Release
submit-for-review: false # TestFlight only for demo builds
- name: wallet-ios-production
project-type: xcode-ios
working-directory: .
config:
xcode-version: "16.1"
scheme: "Wallet Production"
project: "Wallet.xcodeproj"
configuration: Release
submit-for-review: true # Submit to App Store for production
iOS App Store Submission Options
artifacts:
- name: my-ios-app
project-type: xcode-ios
working-directory: .
config:
xcode-version: "16.1"
scheme: "MyApp"
project: "MyApp.xcodeproj"
# App Store submission options
submit-for-review: true # Submit to App Store (not just TestFlight)
skip-validation: false # Validate IPA before upload (recommended)
Monorepo Configuration
Build multiple artifacts from a single repository.
Separate Containers (One Artifact → One Container)
.github/artifacts.yml
artifacts:
- name: backend
project-type: maven
working-directory: java-backend
build-type: application
config:
java-version: 25
- name: frontend
project-type: npm
working-directory: frontend
config:
node-version: 24
containers:
- name: backend
from: [backend]
container-file: java-backend/Containerfile
context: java-backend
- name: frontend
from: [frontend]
container-file: frontend/Containerfile
context: frontend
Combined Container (Multiple Artifacts → One Container)
.github/artifacts.yml
artifacts:
- name: backend
project-type: maven
working-directory: java-backend
- name: frontend
project-type: npm
working-directory: frontend
containers:
- name: full-stack-app
from: [backend, frontend] # Multiple artifacts in one container
container-file: Containerfile
context: .
Containerfile
FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:latest
COPY java-backend/target/*.jar app.jar
COPY frontend/dist/ /app/static/
CMD ["java", "-jar", "app.jar"]
Workflow Configuration
.github/workflows/release-workflow.yml
name: Release Workflow
on:
push:
tags:
- "v[0-9]+.[0-9]+.[0-9]+"
permissions:
contents: read
jobs:
release:
uses: diggsweden/reusable-ci/.github/workflows/release-orchestrator.yml@72b9c326139080c9a9c91999ada2d62d19e7ee54 # v2.7.0
permissions:
contents: write
packages: write
id-token: write
actions: read
attestations: write
secrets: inherit
with:
reusable-ci-ref: v2.7.0
artifacts-config: .github/artifacts.yml
changelog-creator: git-cliff
release-publisher: github-cli
Monorepo Limitations
- Unified versioning: All artifacts share the same version (from git tag)
- Single changelog: One changelog for the entire repository
- No change detection: All artifacts build on every release (smart builds coming in future)
- Sequential version bumps: Artifacts bump versions one at a time (parallel coming in future)
Complete Working Examples
For complete working examples, see the examples/ directory:
- Maven Application:
examples/maven-app/ - NPM Application:
examples/npm-app/ - Gradle JVM Library:
examples/gradle-app/ - Android Application:
examples/android-app/ - Monorepo:
examples/monorepo/