diff --git a/.github/workflows/ci-docker-latest.yml b/.github/workflows/ci-docker-latest.yml new file mode 100644 index 000000000..7d102c07c --- /dev/null +++ b/.github/workflows/ci-docker-latest.yml @@ -0,0 +1,186 @@ +############################################################### +# +# Copyright (c) 2025-2026 International Color Consortium. +# All rights reserved. +# https://color.org +# +# +# Intent: ci-docker-latest +# +# Last Updated: 026-02-13 14:45:57 UTC by David Hoyt +# Update Branch Info +# Test sbom + attest & Test +# Add: artifact-metadata: write +# +# +# +# +############################################################### +# Intent: Build and publish iccDEV Docker container Release +############################################################### + +name: ci-docker-latest + +permissions: + contents: read + packages: write + id-token: write + attestations: write + artifact-metadata: write + +on: + workflow_dispatch: + push: + branches: [master, dockerfiles] + paths: + - 'Dockerfile' + - '.github/workflows/ci-docker-latest.yml' + +jobs: + build: + name: "Build iccDEV Docker" + runs-on: ubuntu-latest + timeout-minutes: 30 + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Lowercase image name + id: image + run: echo "name=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/iccdev-latest" >> "$GITHUB_OUTPUT" + + - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + + - name: Docker meta + id: meta + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 + with: + images: ${{ steps.image.outputs.name }} + tags: | + type=sha + type=raw,value=latest,enable={{is_default_branch}} + - name: Log in to GHCR + if: github.event_name != 'pull_request' + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + id: build-push + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + context: . + file: ./Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + provenance: mode=max + sbom: true + + - name: Generate SBOM + if: github.event_name != 'pull_request' + uses: anchore/sbom-action@2d094306a78d7bde297684f0120dfb41969c38c2 # v0.22.2 + with: + image: ${{ steps.image.outputs.name }}@${{ steps.build-push.outputs.digest }} + format: spdx-json + output-file: sbom.spdx.json + + - name: Attest build provenance + if: github.event_name != 'pull_request' + uses: actions/attest-build-provenance@c44148e5bf178192efd8947e07a0d439a356c60b # v3.2.0 + with: + subject-name: ${{ steps.image.outputs.name }} + subject-digest: ${{ steps.build-push.outputs.digest }} + push-to-registry: true + + - name: Attest SBOM + if: github.event_name != 'pull_request' + uses: actions/attest-sbom@b74e95116c27d38263fc426c93ebfca07aa6197b # v3.0.0 + with: + subject-name: ${{ steps.image.outputs.name }} + subject-digest: ${{ steps.build-push.outputs.digest }} + sbom-path: sbom.spdx.json + push-to-registry: true + + - name: Upload SBOM + if: github.event_name != 'pull_request' + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: iccdev-latest-sbom + path: sbom.spdx.json + retention-days: 90 + + - name: Build local test image + run: docker build -f Dockerfile -t iccdev-test:latest . + + - name: Verify tools + shell: bash + run: | + set -euo pipefail + TOOL_COUNT=$(docker run --rm iccdev-test:latest bash -c \ + 'find /opt/iccdev/Build/Tools -type f -executable | wc -l') + echo "Tools built: $TOOL_COUNT" + if [ "$TOOL_COUNT" -lt 12 ]; then + echo "::error::Expected at least 12 tools, found $TOOL_COUNT" + exit 1 + fi + MISSING=$(docker run --rm iccdev-test:latest bash -c \ + 'ldd /opt/iccdev/Build/Tools/IccToXml/iccToXml 2>&1 | grep -c "not found" || true') + if [ "$MISSING" != "0" ]; then + echo "::error::Missing runtime shared libraries" + docker run --rm iccdev-test:latest bash -c \ + 'ldd /opt/iccdev/Build/Tools/IccToXml/iccToXml 2>&1 | grep "not found"' + exit 1 + fi + echo "### Build Results" >> "$GITHUB_STEP_SUMMARY" + echo "- Tools: $TOOL_COUNT" >> "$GITHUB_STEP_SUMMARY" + echo "- Runtime deps: All resolved ✅" >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + docker run --rm iccdev-test:latest bash -c \ + 'find /opt/iccdev/Build/Tools -type f -executable -exec basename {} \; | sort' \ + >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + - name: Test tool execution + shell: bash + run: | + set -euo pipefail + FAILURES=0 + echo "### Tool Tests" >> "$GITHUB_STEP_SUMMARY" + for tool in iccToXml iccFromXml iccDumpProfile iccRoundTrip; do + OUT=$(docker run --rm iccdev-test:latest "$tool" 2>&1 || true) + if echo "$OUT" | grep -qiE "Usage:|IccProfLib"; then + echo "✅ $tool" >> "$GITHUB_STEP_SUMMARY" + else + echo "::error::Tool test failed: $tool" + echo "❌ $tool" >> "$GITHUB_STEP_SUMMARY" + FAILURES=$((FAILURES + 1)) + fi + done + if [ "$FAILURES" -gt 0 ]; then + echo "::error::$FAILURES tool test(s) failed" + exit 1 + fi + - name: Test iccToXml profile conversion + shell: bash + run: | + set -euo pipefail + echo "### iccToXml Profile Conversion" >> "$GITHUB_STEP_SUMMARY" + docker run --rm iccdev-test:latest bash -c ' + set -euo pipefail + cd /opt/iccdev + iccToXml Testing/sRGB_v4_ICC_preference.icc /tmp/sRGB_v4.xml + test -s /tmp/sRGB_v4.xml || { echo "ERROR: output XML is empty"; exit 1; } + ls -lh /tmp/sRGB_v4.xml + echo "=== First 20 lines of XML output ===" + head -20 /tmp/sRGB_v4.xml + ' 2>&1 | tee /tmp/iccToXml-output.txt + echo '```' >> "$GITHUB_STEP_SUMMARY" + cat /tmp/iccToXml-output.txt >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + - name: Cleanup + if: always() + run: docker rmi iccdev-test:latest || true \ No newline at end of file diff --git a/.github/workflows/ci-docker-nixos.yml b/.github/workflows/ci-docker-nixos.yml new file mode 100644 index 000000000..d6e2ebc41 --- /dev/null +++ b/.github/workflows/ci-docker-nixos.yml @@ -0,0 +1,177 @@ +############################################################### +# +# Copyright (c) 2025-2026 International Color Consortium. +# All rights reserved. +# https://color.org +# +# +# Intent: ci-docker-nixos +# +# Last Updated: 2026-02-13 13:58:11 UTC by David Hoyt +# Initial workflow with SBOM + attestations +# Test Updated Scoping +# +############################################################### +# Intent: Build and publish iccDEV NixOS Docker container +############################################################### + +name: ci-docker-nixos + +permissions: + contents: read + packages: write + id-token: write + attestations: write + artifact-metadata: write + +on: + workflow_dispatch: + push: + branches: [master, dockerfiles] + paths: + - 'Dockerfile.nixos' + - '.github/workflows/ci-docker-nixos.yml' + +jobs: + build: + name: "Build iccDEV NixOS Docker" + runs-on: ubuntu-latest + timeout-minutes: 45 + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Lowercase image name + id: image + run: echo "name=ghcr.io/${GITHUB_REPOSITORY_OWNER,,}/iccdev-nixos" >> "$GITHUB_OUTPUT" + + - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + + - name: Docker meta + id: meta + uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0 + with: + images: ${{ steps.image.outputs.name }} + tags: | + type=sha + type=raw,value=latest,enable={{is_default_branch}} + + - name: Log in to GHCR + if: github.event_name != 'pull_request' + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + id: build-push + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 + with: + context: . + file: ./Dockerfile.nixos + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + provenance: mode=max + sbom: true + + - name: Generate SBOM + if: github.event_name != 'pull_request' + uses: anchore/sbom-action@2d094306a78d7bde297684f0120dfb41969c38c2 # v0.22.2 + with: + image: ${{ steps.image.outputs.name }}@${{ steps.build-push.outputs.digest }} + format: spdx-json + output-file: sbom.spdx.json + + - name: Attest build provenance + if: github.event_name != 'pull_request' + uses: actions/attest-build-provenance@c44148e5bf178192efd8947e07a0d439a356c60b # v3.2.0 + with: + subject-name: ${{ steps.image.outputs.name }} + subject-digest: ${{ steps.build-push.outputs.digest }} + push-to-registry: true + + - name: Attest SBOM + if: github.event_name != 'pull_request' + uses: actions/attest-sbom@b74e95116c27d38263fc426c93ebfca07aa6197b # v3.0.0 + with: + subject-name: ${{ steps.image.outputs.name }} + subject-digest: ${{ steps.build-push.outputs.digest }} + sbom-path: sbom.spdx.json + push-to-registry: true + + - name: Upload SBOM + if: github.event_name != 'pull_request' + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: iccdev-nixos-sbom + path: sbom.spdx.json + retention-days: 90 + + - name: Build local test image + run: docker build -f Dockerfile.nixos -t iccdev-nixos-test:latest . + + - name: Verify tools + shell: bash + run: | + set -euo pipefail + TOOL_COUNT=$(docker run --rm iccdev-nixos-test:latest sh -c \ + 'find /workspace/iccDEV/Build/Tools -type f -executable | wc -l') + echo "Tools built: $TOOL_COUNT" + if [ "$TOOL_COUNT" -lt 12 ]; then + echo "::error::Expected at least 12 tools, found $TOOL_COUNT" + exit 1 + fi + echo "### NixOS Build Results" >> "$GITHUB_STEP_SUMMARY" + echo "- Tools: $TOOL_COUNT" >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + docker run --rm iccdev-nixos-test:latest sh -c \ + 'find /workspace/iccDEV/Build/Tools -type f -executable -exec basename {} \; | sort' \ + >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + + - name: Test tool execution + shell: bash + run: | + set -euo pipefail + FAILURES=0 + echo "### Tool Tests" >> "$GITHUB_STEP_SUMMARY" + for tool in iccToXml iccFromXml iccDumpProfile iccRoundTrip; do + OUT=$(docker run --rm iccdev-nixos-test:latest "$tool" 2>&1 || true) + if echo "$OUT" | grep -qiE "Usage:|IccProfLib"; then + echo "✅ $tool" >> "$GITHUB_STEP_SUMMARY" + else + echo "::error::Tool test failed: $tool" + echo "❌ $tool" >> "$GITHUB_STEP_SUMMARY" + FAILURES=$((FAILURES + 1)) + fi + done + if [ "$FAILURES" -gt 0 ]; then + echo "::error::$FAILURES tool test(s) failed" + exit 1 + fi + + - name: Test iccToXml profile conversion + shell: bash + run: | + set -euo pipefail + echo "### iccToXml Profile Conversion" >> "$GITHUB_STEP_SUMMARY" + docker run --rm iccdev-nixos-test:latest sh -c ' + set -euo pipefail + cd /workspace/iccDEV + iccToXml Testing/sRGB_v4_ICC_preference.icc /tmp/sRGB_v4.xml + test -s /tmp/sRGB_v4.xml || { echo "ERROR: output XML is empty"; exit 1; } + ls -lh /tmp/sRGB_v4.xml + echo "=== First 20 lines of XML output ===" + head -20 /tmp/sRGB_v4.xml + ' 2>&1 | tee /tmp/iccToXml-output.txt + echo '```' >> "$GITHUB_STEP_SUMMARY" + cat /tmp/iccToXml-output.txt >> "$GITHUB_STEP_SUMMARY" + echo '```' >> "$GITHUB_STEP_SUMMARY" + + - name: Cleanup + if: always() + run: docker rmi iccdev-nixos-test:latest || true diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..fa17fc761 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,60 @@ +############################################################### +# Copyright (c) 2025-2026 International Color Consortium. +# All rights reserved. +# https://color.org +# +# Intent: iccDEV ci-docker-build +# +# Last Updated: 2026-02-12 00:14:22 UTC by David Hoyt +# +############################################################### + +FROM ubuntu:26.04 AS builder +ENV DEBIAN_FRONTEND=noninteractive + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + build-essential cmake make git ca-certificates \ + libxml2-dev nlohmann-json3-dev \ + libtiff-dev libjpeg-dev libpng-dev zlib1g-dev \ + && rm -rf /var/lib/apt/lists/* + +RUN git clone --depth 1 https://github.com/InternationalColorConsortium/iccDEV.git /opt/iccdev \ + && cd /opt/iccdev \ + && sed -i '/find_package(wxWidgets COMPONENTS core base REQUIRED)/,/endif()/ s/^/# /' Build/Cmake/CMakeLists.txt \ + && cd Build \ + && cmake -DCMAKE_BUILD_TYPE=Release Cmake \ + && make -j"$(nproc)" \ + && rm -rf /opt/iccdev/.git + +RUN echo "=== Libraries ===" \ + && ls -lh /opt/iccdev/Build/IccProfLib/libIccProfLib2* \ + && ls -lh /opt/iccdev/Build/IccXML/libIccXML2* \ + && echo "=== Tools ===" \ + && find /opt/iccdev/Build/Tools -type f -executable | sort + +FROM ubuntu:26.04 +ENV DEBIAN_FRONTEND=noninteractive + +LABEL org.opencontainers.image.title="iccDEV Build Container" \ + org.opencontainers.image.description="Container v2.0.0.82" \ + org.opencontainers.image.licenses="BSD-3-Clause" \ + org.opencontainers.image.vendor="International Color Consortium" \ + org.opencontainers.image.source="https://github.com/InternationalColorConsortium/iccDEV" + +RUN apt-get update && apt-get install -y --no-install-recommends \ + libxml2-16 libtiff6 libjpeg8 libpng16-16t64 zlib1g \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=builder /opt/iccdev /opt/iccdev + +RUN groupadd -r iccdev \ + && useradd -r -g iccdev -d /opt/iccdev -s /bin/bash iccdev \ + && chown -R iccdev:iccdev /opt/iccdev + +ENV PATH="/opt/iccdev/Build/Tools/IccToXml:/opt/iccdev/Build/Tools/IccFromXml:/opt/iccdev/Build/Tools/IccDumpProfile:/opt/iccdev/Build/Tools/IccApplyNamedCmm:/opt/iccdev/Build/Tools/IccRoundTrip:/opt/iccdev/Build/Tools/IccFromCube:/opt/iccdev/Build/Tools/IccApplyProfiles:/opt/iccdev/Build/Tools/IccApplySearch:/opt/iccdev/Build/Tools/IccApplyToLink:/opt/iccdev/Build/Tools/IccPngDump:/opt/iccdev/Build/Tools/IccSpecSepToTiff:/opt/iccdev/Build/Tools/IccTiffDump:/opt/iccdev/Build/Tools/IccV5DspObsToV4Dsp:${PATH}" + +USER iccdev +WORKDIR /opt/iccdev + +CMD ["bash"] \ No newline at end of file diff --git a/Dockerfile.nixos b/Dockerfile.nixos new file mode 100644 index 000000000..a7d7864da --- /dev/null +++ b/Dockerfile.nixos @@ -0,0 +1,132 @@ +############################################################### +# Copyright (c) 2025-2026 International Color Consortium. +# All rights reserved. +# https://color.org +# +# Dockerfile for iccDEV Build Container using NixOS +# Based on nixos/nix Docker image +# +# Last Updated: 2026-02-09 23:50:57 UTC by David Hoyt +# +# Build command: +# docker build -f Dockerfile.nixos -t iccdev-nixos:latest . +# +# Run command: +# docker run -it --rm iccdev-nixos:latest +# +# Testing with volume mount: +# docker run -it --rm -v /path/to/icc/files:/data iccdev-nixos:latest +# +############################################################### + +# Use official NixOS Docker image +FROM nixos/nix:latest + +LABEL org.opencontainers.image.title="iccDEV Build Container (NixOS)" \ + org.opencontainers.image.description="iccDEV built with Nix package manager" \ + org.opencontainers.image.licenses="BSD-3-Clause" \ + org.opencontainers.image.vendor="International Color Consortium" \ + org.opencontainers.image.source="https://github.com/InternationalColorConsortium/iccDEV" \ + org.opencontainers.image.url="https://github.com/InternationalColorConsortium/iccDEV" \ + org.opencontainers.image.documentation="https://github.com/InternationalColorConsortium/iccDEV/tree/master/docs" + +# Set working directory +WORKDIR /workspace + +# Clone iccDEV repository and build using nix-shell +# Build from HEAD with all dependencies including wxWidgets +RUN nix-shell -p git cmake gcc gnumake pkg-config libxml2 libtiff libjpeg libpng nlohmann_json zlib wxGTK32 --run ' \ + export NIX_LDFLAGS="-ltiff $NIX_LDFLAGS" && \ + git clone https://github.com/InternationalColorConsortium/iccDEV.git /workspace/iccDEV && \ + cd /workspace/iccDEV && \ + echo "=== Building iccDEV from HEAD ===" && \ + git log -1 --oneline && \ + cd Build && \ + cmake Cmake && \ + make -j$(nproc) && \ + echo "=== Build Complete ===" && \ + echo "Built tools:" && \ + find ./Tools -name "icc*" -type f -executable | wc -l && \ + echo "Built libraries:" && \ + find . -name "*.so*" -o -name "*.a" | grep -E "IccProf|IccXML" | wc -l \ + ' + +# Set PATH to include all built tools +ENV PATH="/workspace/iccDEV/Build/Tools/IccApplyNamedCmm:\ +/workspace/iccDEV/Build/Tools/IccApplyProfiles:\ +/workspace/iccDEV/Build/Tools/IccApplySearch:\ +/workspace/iccDEV/Build/Tools/IccApplyToLink:\ +/workspace/iccDEV/Build/Tools/IccDumpProfile:\ +/workspace/iccDEV/Build/Tools/IccFromCube:\ +/workspace/iccDEV/Build/Tools/IccFromXml:\ +/workspace/iccDEV/Build/Tools/IccJpegDump:\ +/workspace/iccDEV/Build/Tools/IccPngDump:\ +/workspace/iccDEV/Build/Tools/IccRoundTrip:\ +/workspace/iccDEV/Build/Tools/IccSpecSepToTiff:\ +/workspace/iccDEV/Build/Tools/IccTiffDump:\ +/workspace/iccDEV/Build/Tools/IccToXml:\ +/workspace/iccDEV/Build/Tools/IccV5DspObsToV4Dsp:\ +/workspace/iccDEV/Build/Tools/wxProfileDump:\ +${PATH}" + +# Set library path +ENV LD_LIBRARY_PATH="/workspace/iccDEV/Build/IccProfLib:/workspace/iccDEV/Build/IccXML" + +# Set working directory to iccDEV +WORKDIR /workspace/iccDEV + +# Create welcome script in workspace +RUN cat > /workspace/welcome.sh << 'EOF' +#!/usr/bin/env sh +echo "" +echo "============================================================" +echo "==== International Color Consortium | https://color.org ====" +echo "==== iccDEV Build Container (NixOS) ========================" +echo "============================================================" +echo "" +echo "All iccDEV tools are available on PATH:" +echo "" +echo "Command-line tools (14):" +echo " - iccApplyNamedCmm - iccFromXml" +echo " - iccApplyProfiles - iccJpegDump" +echo " - iccApplySearch - iccPngDump" +echo " - iccApplyToLink - iccRoundTrip" +echo " - iccDumpProfile - iccSpecSepToTiff" +echo " - iccFromCube - iccTiffDump" +echo " - iccToXml - iccV5DspObsToV4Dsp" +echo "" +echo "GUI tool (1):" +echo " - iccDumpProfileGui" +echo "" +echo "iccDEV Libraries (in /workspace/iccDEV/Build):" +echo "" +echo "Shared Libraries (.so):" +echo " - IccProfLib/libIccProfLib2.so.2.3.1.4" +echo " - IccXML/libIccXML2.so.2.3.1.4" +echo "" +echo "Static Libraries (.a):" +echo " - IccProfLib/libIccProfLib2-static.a" +echo " - IccXML/libIccXML2-static.a" +echo "" +echo "Example usage:" +echo " iccDumpProfile Testing/sRGB_v4_ICC_preference.icc ALL" +echo " iccToXml Testing/sRGB_v4_ICC_preference.icc output.xml" +echo "" +echo "Testing directory: /workspace/iccDEV/Testing" +echo "Build directory: /workspace/iccDEV/Build" +echo "" +echo "To list all tools and libraries:" +echo " find Build/Tools -type f -executable -name 'icc*'" +echo " find Build -name 'libIcc*.so*' -o -name 'libIcc*.a'" +echo "" +echo "To run all tests:" +echo " cd Testing && sh CreateAllProfiles.sh" +echo "" +echo "================================================" +echo "" +EOF + +RUN chmod +x /workspace/welcome.sh + +# Default command: show welcome and start interactive shell +CMD ["sh", "-c", "/workspace/welcome.sh && exec sh"]