Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
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
2 changes: 1 addition & 1 deletion .devcontainer/cpp/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ RUN --mount=from=downloader,target=/dl \
ARM_GNU_TOOLCHAIN_SHA256="d061559d814b205ed30c5b7c577c03317ec447ca51cd5a159d26b12a5bbeb20c"
fi

wget --no-hsts -qO "${ARM_GNU_TOOLCHAIN_TAR}" "${ARM_GNU_TOOLCHAIN_URL}"
wget --no-hsts --https-only -qO "${ARM_GNU_TOOLCHAIN_TAR}" "${ARM_GNU_TOOLCHAIN_URL}"
Comment thread
rjaegers marked this conversation as resolved.
Outdated
echo "${ARM_GNU_TOOLCHAIN_SHA256} ${ARM_GNU_TOOLCHAIN_TAR}" | sha256sum -c -

tar xJf "${ARM_GNU_TOOLCHAIN_TAR}" --exclude="*arm-none-eabi-gdb*" --exclude="share"
Expand Down
85 changes: 85 additions & 0 deletions .github/actions/generate-tool-inventory/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
name: Generate tool inventory
description: >-
Derive a curated, per-flavor tool inventory from a Syft SPDX SBOM and write it
to a JSON file.

inputs:
sbom:
description: Path to the Syft SPDX SBOM
required: true
allowlist:
description: >-
Path to the flavor's tool allowlist JSON, relative to the caller
repository root. The file is sparse-checked-out by this action.
required: true
flavor:
description: Name of the flavor the inventory is generated for
required: true
output-file:
description: Path the generated tool inventory is written to
required: false
default: tool-inventory.json

outputs:
inventory-file:
description: Path to the generated tool inventory JSON file
value: ${{ inputs.output-file }}

runs:
using: composite
steps:
# The allowlist lives in the caller repository; check out just that file so
# the action is self-contained and callers need no separate checkout step.
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
sparse-checkout: ${{ inputs.allowlist }}
sparse-checkout-cone-mode: false
path: ${{ runner.temp }}/allowlist
- shell: bash
Comment thread
rjaegers marked this conversation as resolved.
run: |
set -Eeuo pipefail

# Keep only packages whose name is on the flavor allowlist and project them
# to {name, version, purl}. Versions come straight from the SBOM, so the
# inventory can never disagree with it.
inventory="$(jq -n \
--slurpfile sbom "${SBOM}" \
--slurpfile allow "${ALLOWLIST}" \
--arg flavor "${FLAVOR}" '
($allow[0] | map(ascii_downcase)) as $names
| [ $sbom[0].packages[]
| select(.name != null)
| . as $pkg
| select($names | index($pkg.name | ascii_downcase))
| { name: $pkg.name,
version: $pkg.versionInfo,
purl: ([ $pkg.externalRefs[]? | select(.referenceType == "purl") | .referenceLocator ] | first) } ]
| unique_by(.name | ascii_downcase)
| sort_by(.name | ascii_downcase)
| { flavor: $flavor, tools: . }')"

# Fail if an allowlisted tool is absent from the SBOM. This turns a version
# bump that renames a package (e.g. clang-22 -> clang-23) or a tool that
# silently dropped out of the image into a hard, actionable CI error.
missing="$(jq -rn \
--argjson inventory "${inventory}" \
--slurpfile allow "${ALLOWLIST}" '
($inventory.tools | map(.name | ascii_downcase)) as $found
| $allow[0]
| map(select((ascii_downcase) as $name | ($found | index($name)) | not))
| .[]')"

if [ -n "${missing}" ]; then
echo "error: the following allowlisted tools were not found in the SBOM:" >&2
echo "${missing}" | sed 's/^/ - /' >&2
exit 1
fi

echo "${inventory}" | tee "${OUTPUT_FILE}"
env:
SBOM: ${{ inputs.sbom }}
ALLOWLIST: ${{ runner.temp }}/allowlist/${{ inputs.allowlist }}
FLAVOR: ${{ inputs.flavor }}
OUTPUT_FILE: ${{ inputs.output-file }}
63 changes: 63 additions & 0 deletions .github/actions/merge-devcontainer-metadata/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
name: Merge devcontainer.metadata
description: >-
Assemble the devcontainer.metadata image label for a flavor by concatenating
the base image's existing metadata array with the flavor's own metadata entry.

inputs:
base-image:
description: Reference of the image this flavor is built FROM (may be empty)
required: false
default: ""
devcontainer-metadata-file:
description: Path to the flavor's devcontainer-metadata.json (may be absent)
required: false
default: ""

outputs:
label:
description: >-
The `devcontainer.metadata=<json-array>` label value, or empty when no
metadata file is provided.
value: ${{ steps.merge.outputs.label }}

runs:
using: composite
steps:
- id: merge
shell: bash
run: |
set -Eeuo pipefail

if [ -z "${DEVCONTAINER_METADATA_FILE:-}" ] || [ ! -f "${DEVCONTAINER_METADATA_FILE}" ]; then
echo "devcontainer-metadata-file input not set or file does not exist, skipping devcontainer.metadata label"
echo "label=" >> "$GITHUB_OUTPUT"
exit 0
fi

# Extract the base image's existing devcontainer.metadata array. Falls back
# to an empty array when no base image is given or it carries no such label.
base_metadata="[]"
if [ -n "${BASE_IMAGE:-}" ]; then
# `.Image` is the image config for single-platform references and a map of
# `platform -> config` for multi-platform references; the label is identical
# across platforms, so any entry works.
config="$(docker buildx imagetools inspect "${BASE_IMAGE}" --format '{{json .Image}}')"
base_metadata="$(jq -c '
(if has("config") then . else (to_entries[0].value) end)
| (.config.Labels["devcontainer.metadata"] // "") as $raw
| if $raw == "" then [] else (try ($raw | fromjson) catch []) end
| if type == "array" then . else [] end
' <<< "${config}")"
fi

# Concatenate base entries with the flavor entry and emit the label value.
# The gsub adds a space after each comma so `docker buildx build --label`
# does not misinterpret the array and produce invalid JSON (e.g.
# ["x","y"] -> ["x",y]).
merged="$(jq -cr --slurpfile flavor "${DEVCONTAINER_METADATA_FILE}" '. + $flavor | @json | gsub("\",\""; "\", \"")' <<< "${base_metadata}")"

echo "label=devcontainer.metadata=${merged}" >> "$GITHUB_OUTPUT"
env:
BASE_IMAGE: ${{ inputs.base-image }}
DEVCONTAINER_METADATA_FILE: ${{ inputs.devcontainer-metadata-file }}
50 changes: 0 additions & 50 deletions .github/scripts/generate-tool-inventory.sh

This file was deleted.

58 changes: 0 additions & 58 deletions .github/scripts/merge-devcontainer-metadata.sh

This file was deleted.

54 changes: 16 additions & 38 deletions .github/workflows/wc-build-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,26 +102,14 @@
id: metadata
with:
images: ${{ needs.sanitize-image-name.outputs.fully-qualified-image-name }}
# Merge the base image's devcontainer.metadata array with this flavor's
# entry so that flavors inherit base metadata without duplicating it.
- name: Generate image label for devcontainer.metadata
run: |
set -Eeuo pipefail

if [ -z "${DEVCONTAINER_METADATA_FILE:-}" ] || [ ! -f "${DEVCONTAINER_METADATA_FILE}" ]; then
echo "devcontainer-metadata-file input not set or file does not exist, skipping devcontainer.metadata label"
echo "label=" >> "$GITHUB_OUTPUT"
exit 0
fi

# Merge the base image's devcontainer.metadata array with this flavor's
# entry so that flavors inherit base metadata without duplicating it.
{
echo -n "label="
bash .github/scripts/merge-devcontainer-metadata.sh "${BASE_IMAGE:-}" "${DEVCONTAINER_METADATA_FILE}"
} >> "$GITHUB_OUTPUT"
env:
BASE_IMAGE: ${{ inputs.base-image }}
DEVCONTAINER_METADATA_FILE: ${{ inputs.devcontainer-metadata-file }}
uses: philips-software/amp-devcontainer/.github/actions/merge-devcontainer-metadata@6934e07c72c5cc8d89128a5609981e4eb8737d67 # fix/package-scripts-as-actions

Check warning

Code scanning / zizmor

action's hash pin has mismatched or missing version comment: points to commit 713b05adf03e Warning

action's hash pin has mismatched or missing version comment: points to commit 713b05adf03e

Check notice

Code scanning / zizmor

commit hash does not point to a Git tag: this step Note

commit hash does not point to a Git tag: this step
id: devcontainer-metadata
with:
base-image: ${{ inputs.base-image }}
devcontainer-metadata-file: ${{ inputs.devcontainer-metadata-file }}
- run: echo "git-commit-epoch=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT"
id: devcontainer-epoch
- run: echo "arch=$(echo "${RUNNER_ARCH}" | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -294,30 +282,20 @@
registry-password: ${{ secrets.DOCKER_REGISTRY_PASSWORD || github.token }}
dependency-snapshot: true
output-file: ${{ runner.temp }}/sbom.spdx.json
- name: Derive tool inventory from SBOM
if: ${{ inputs.tool-inventory-file }}
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
sparse-checkout: |
.github/scripts/generate-tool-inventory.sh
${{ inputs.tool-inventory-file }}
sparse-checkout-cone-mode: false
- name: Generate tool inventory
if: ${{ inputs.tool-inventory-file }}
run: |
set -Eeuo pipefail
bash .github/scripts/generate-tool-inventory.sh \
"${SBOM}" "${ALLOWLIST}" "${FLAVOR}" | tee tool-inventory.json
env:
SBOM: ${{ runner.temp }}/sbom.spdx.json
ALLOWLIST: ${{ inputs.tool-inventory-file }}
FLAVOR: ${{ needs.sanitize-image-name.outputs.image-basename }}
if: ${{ inputs.tool-inventory-file != '' }}
id: generate-tool-inventory
uses: philips-software/amp-devcontainer/.github/actions/generate-tool-inventory@6934e07c72c5cc8d89128a5609981e4eb8737d67 # fix/package-scripts-as-actions

Check warning

Code scanning / zizmor

action's hash pin has mismatched or missing version comment: points to commit 713b05adf03e Warning

action's hash pin has mismatched or missing version comment: points to commit 713b05adf03e

Check notice

Code scanning / zizmor

commit hash does not point to a Git tag: this step Note

commit hash does not point to a Git tag: this step
with:
sbom: ${{ runner.temp }}/sbom.spdx.json
allowlist: ${{ inputs.tool-inventory-file }}
flavor: ${{ needs.sanitize-image-name.outputs.image-basename }}
output-file: ${{ runner.temp }}/tool-inventory.json
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ inputs.tool-inventory-file }}
if: ${{ inputs.tool-inventory-file != '' }}
with:
name: tool-inventory-${{ needs.sanitize-image-name.outputs.image-basename }}
path: tool-inventory.json
path: ${{ steps.generate-tool-inventory.outputs.inventory-file }}
retention-days: 10
- uses: actions/attest@a1948c3f048ba23858d222213b7c278aabede763 # v4.1.1
with:
Expand Down
Loading