version: 2.1

commands:
  build_board:
    parameters:
      arch:
        type: string
      target:
        type: string
      subcommand:
        type: string
    steps:
      - run:
          name: Make Board (console logs not contiguous because multiple CPUs used to build under CircleCI, see logs in artifacts or Output build failing logs below in case of failed step)
          command: |
            echo "Sourcing /devenv.sh since docker entrypoint doesn't do it as expected"
            source /devenv.sh
            rm -rf build/<< parameters.arch >>/<< parameters.target >>/* build/<< parameters.arch >>/log/*
            #Force -j8 so that each make subtask consumes 1gb max and force respect of minimal requirements of CircleCI which otherwise randomly fails
            make V=1 BOARD=<< parameters.target >> << parameters.subcommand >> AVAILABLE_MEM_GB=8  | ts || touch ./tmpDir/failed_build
          no_output_timeout: 3h
      - run:
          name: Output hashes
          command: |
            cat build/<< parameters.arch >>/<< parameters.target >>/hashes.txt || echo "No hashes.txt for this build step..."
      - run:
          name: Output sizes
          command: |
            cat build/<< parameters.arch >>/<< parameters.target >>/sizes.txt || echo "No sizes.txt for this build step..."
      - run:
          name: Archiving build logs.
          command: |
            tar zcvf build/<< parameters.arch >>/<< parameters.target >>/logs.tar.gz $(find build/ -name "*.log")
      - run:
          name: Output build failing logs
          command: |
            if [[ -f ./tmpDir/failed_build ]]; then
              find "./build/<< parameters.arch >>/" -name "*.log" -type f -mmin -1 -exec tail -n +1 '{}' +
              exit 1
            else
              echo "Step hasn't failed. Continuing with next step..."
            fi
      - store_artifacts:
          path: build/<< parameters.arch >>/<< parameters.target >>

jobs:
  prep_env:
    docker:
      - image: tlaurion/heads-dev-env:v0.2.4
    resource_class: large
    working_directory: ~/heads
    steps:
      - checkout
      - run:
          name: git reset
          command: |
            git reset --hard "$CIRCLE_SHA1"
      - run:
          name: Make tmp dir
          command: |
            mkdir ./tmpDir
      - run:
          name: Creating all modules and patches digest (All modules cache digest)
          command: |
            find .circleci/config.yml ./Makefile ./flake.lock ./patches/ ./modules/ -type f | sort -h |xargs sha256sum > ./tmpDir/all_modules_and_patches.sha256sums
      - run:
          name: Creating coreboot (and associated patches) and musl-cross-make modules digest (musl-cross-make and coreboot cache digest)
          command: |
            find .circleci/config.yml ./Makefile ./flake.lock ./modules/coreboot ./modules/musl-cross-make* ./patches/coreboot* -type f | sort -h | xargs sha256sum > ./tmpDir/coreboot_musl-cross-make.sha256sums
      - run:
          name: Creating musl-cross-make and musl-cross-make patches digest (musl-cross-make cache digest)
          command: |
            find .circleci/config.yml ./Makefile ./flake.lock modules/musl-cross-make* -type f | sort -h | xargs sha256sum > ./tmpDir/musl-cross-make.sha256sums
      - restore_cache:
          # First matched/found key wins and following keys are not tried
          keys:
            # Cache for matching modules digest, validated to be exactly the same as in GitHub current commit.
            # This cache was made on top of below caches, if previously existing.
            # If no module definition changed, we reuse this one
            - nix-docker-heads-modules-and-patches-{{ checksum "./tmpDir/all_modules_and_patches.sha256sums" }}{{ .Environment.CACHE_VERSION }}

            # Cache for coreboot module (and patches) and musl-cross-make digests (coreboot: triannual release)
            - nix-docker-heads-coreboot-musl-cross-make-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}

            # Cache for musl-cross-make module digest (rarely modified).
            - nix-docker-heads-musl-cross-make-{{ checksum "./tmpDir/musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
      - run:
          name: Download and neuter xx20 ME (keep generated GBE and extracted IFD in tree)
          command: |
            ./blobs/xx20/download_parse_me.sh
      - run:
          name: Download Optiplex 7010/9010 blobs
          command: |
            ./blobs/xx30/optiplex_7010_9010.sh ./blobs/xx30
      # me_cleaner.py present under heads blobs/utils/me_cleaner dir comes from https://github.com/corna/me_cleaner/blob/43612a630c79f3bc6f2653bfe90dfe0b7b137e08/me_cleaner.py
      - run:
          name: Download and neuter xx30 ME (keep generated GBE and extracted IFD in tree)
          command: |
            ./blobs/xx30/download_clean_me_manually.sh -m $(readlink -f ./blobs/utils/me_cleaner/me_cleaner.py)
      - run:
          name: Download, neuter and deguard xx80 ME (keep generated GBE and extracted IFD in tree)
          command: |
            ./blobs/xx80/download_clean_deguard_me_pad_tb.sh -m $(readlink -f ./blobs/utils/me_cleaner/me_cleaner.py) ./blobs/xx80/
      - run:
          name: Download and extract t530 vbios roms for dgpu boards
          command: |
            echo skipping for now
            exit 0
            ./blobs/xx30/vbios_t530.sh
      - run:
          name: Download and extract w530 vbios roms for dgpu boards
          command: |
            echo skipping for now
            exit 0
            ./blobs/xx30/vbios_w530.sh
      - persist_to_workspace:
          root: ~/heads
          paths:
            - .

  build_and_persist:
    docker:
      - image: tlaurion/heads-dev-env:v0.2.4
    resource_class: large
    working_directory: ~/heads
    parameters:
      arch:
        type: string
        default: x86
      target:
        type: string
      subcommand:
        type: string
    steps:
      - attach_workspace:
          at: ~/heads
      - build_board:
          arch: << parameters.arch >>
          target: << parameters.target >>
          subcommand: << parameters.subcommand >>
      - persist_to_workspace:
          root: ~/heads
          paths:
            - packages/<< parameters.arch >>
            - build/<< parameters.arch >>
            - crossgcc/<< parameters.arch >>
            - install/<< parameters.arch >>

  build:
    docker:
      - image: tlaurion/heads-dev-env:v0.2.4
    resource_class: large
    working_directory: ~/heads
    parameters:
      arch:
        type: string
        default: x86
      target:
        type: string
      subcommand:
        type: string
    steps:
      - attach_workspace:
          at: ~/heads
      - build_board:
          arch: <<parameters.arch>>
          target: <<parameters.target>>
          subcommand: <<parameters.subcommand>>

  save_cache:
    docker:
      - image: tlaurion/heads-dev-env:v0.2.4
    resource_class: large
    working_directory: ~/heads
    steps:
      - attach_workspace:
          at: ~/heads
      - save_cache:
          # Generate cache for the same musl-cross-make module definition if hash is not previously existing
          # CircleCI removed their wildcard support, so we have to list precise versions to cache in directory names
          key: nix-docker-heads-musl-cross-make-{{ checksum "./tmpDir/musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
          paths:
            - build/ppc64/musl-cross-make-38e52db8358c043ae82b346a2e6e66bc86a53bc1
            - build/x86/musl-cross-make-38e52db8358c043ae82b346a2e6e66bc86a53bc1
            - crossgcc
            - packages
      - save_cache:
          # Generate cache for the same coreboot and musl-cross-make modules definition if hash is not previously existing
          # CircleCI removed their wildcard support, so we have to list precise versions to cache in directory names
          key: nix-docker-heads-coreboot-musl-cross-make-{{ checksum "./tmpDir/coreboot_musl-cross-make.sha256sums" }}{{ .Environment.CACHE_VERSION }}
          paths:
            - build/ppc64/coreboot-talos_2
            - build/ppc64/musl-cross-make-38e52db8358c043ae82b346a2e6e66bc86a53bc1
            - build/x86/coreboot-4.11
            - build/x86/coreboot-24.02.01
            - build/x86/coreboot-24.12
            - build/x86/coreboot-dasharo
            - build/x86/coreboot-purism
            - build/x86/musl-cross-make-38e52db8358c043ae82b346a2e6e66bc86a53bc1
            - crossgcc
            - packages
      - save_cache:
          # Generate cache for the exact same modules definitions if hash is not previously existing
          key: nix-docker-heads-modules-and-patches-{{ checksum "./tmpDir/all_modules_and_patches.sha256sums" }}{{ .Environment.CACHE_VERSION }}
          paths:
            - build
            - crossgcc
            - install
            - packages

workflows:
  version: 2
  build_and_test:
    jobs:
      - prep_env

      # This step builds musl-cross-make for x86 architecture, which will be used by subsequent x86 board builds
      - build_and_persist:
          name: x86-musl-cross-make
          target: x230-hotp-maximized
          subcommand: "musl-cross-make"
          requires:
            - prep_env

      # This step builds musl-cross-make for ppc64 architecture, which will be used by subsequent ppc64 board builds
      - build_and_persist:
          name: ppc64-musl-cross-make
          arch: ppc64
          target: UNTESTED_talos-2
          subcommand: "musl-cross-make"
          requires:
            - prep_env

      # Below, sequentially build one board for each coreboot version.
      # The last board in the sequence is the dependency for the parallel boards built at the end, and also save_cache.

      # coreboot 24.02.01
      - build_and_persist:
          name: novacustom-nv4x_adl
          target: novacustom-nv4x_adl
          subcommand: ""
          requires:
            - x86-musl-cross-make

      # coreboot purism: based on coreboot 24.02.01, reuse dasharo 24.02.01 crossgcc
      - build_and_persist:
          name: librem_14
          target: librem_14
          subcommand: ""
          requires:
            - novacustom-nv4x_adl

      # t480 is based on 24.12 coreboot release, not sharing any buildstack from now, depend on muscl-cross cache
      - build_and_persist:
          name: t480-hotp-maximized
          target: t480-hotp-maximized
          subcommand: ""
          requires:
            - x86-musl-cross-make

      # coreboot talos_2
      - build_and_persist:
          name: UNTESTED_talos-2
          arch: ppc64
          target: UNTESTED_talos-2
          subcommand: ""
          requires:
            - ppc64-musl-cross-make

      # coreboot 4.11
      - build_and_persist:
          name: librem_l1um
          target: librem_l1um
          subcommand: ""
          requires:
            - x86-musl-cross-make

      # Cache one workspace per architecture
      # Make sure workspace caches are chainloaded and the last in chain for an arch is saved
      - save_cache:
          requires:
            - UNTESTED_talos-2
            - t480-hotp-maximized

      # Those onboarding new boards should add their entries below.
      # coreboot 24.12 boards
      - build:
          name: x220-hotp-maximized
          target: x220-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: x220-maximized
          target: x220-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: t420-hotp-maximized
          target: t420-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: t420-maximized
          target: t420-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: x230-hotp-maximized_usb-kb
          target: x230-hotp-maximized_usb-kb
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: t430-hotp-maximized
          target: t430-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: x230-maximized
          target: x230-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      #TODO: move away of 24.02.01 coreboot and depend on optiplex specific dasharo commit
      - build:
          name: optiplex-7010_9010-maximized
          target: optiplex-7010_9010-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: optiplex-7010_9010-hotp-maximized
          target: optiplex-7010_9010-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: optiplex-7010_9010_TXT-maximized
          target: optiplex-7010_9010_TXT-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: optiplex-7010_9010_TXT-hotp-maximized
          target: optiplex-7010_9010_TXT-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: x230-maximized-fhd_edp
          target: x230-maximized-fhd_edp
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: x230-hotp-maximized-fhd_edp
          target: x230-hotp-maximized-fhd_edp
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: w530-hotp-maximized
          target: w530-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: t430-maximized
          target: t430-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: w530-maximized
          target: w530-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: t530-maximized
          target: t530-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: t530-hotp-maximized
          target: t530-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: UNTESTED_t440p-maximized
          target: UNTESTED_t440p-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: UNTESTED_t440p-hotp-maximized
          target: UNTESTED_t440p-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: UNTESTED_w541-maximized
          target: UNTESTED_w541-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: UNTESTED_w541-hotp-maximized
          target: UNTESTED_w541-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: qemu-coreboot-fbwhiptail-tpm2-hotp
          target: qemu-coreboot-fbwhiptail-tpm2-hotp
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: z220-cmt-maximized
          target: z220-cmt-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      - build:
          name: z220-cmt-hotp-maximized
          target: z220-cmt-hotp-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      # coreboot purism
      # librem boards
      - build:
          name: librem_13v2
          target: librem_13v2
          subcommand: ""
          requires:
            - librem_14

      - build:
          name: librem_15v3
          target: librem_15v3
          subcommand: ""
          requires:
            - librem_14

      - build:
          name: librem_13v4
          target: librem_13v4
          subcommand: ""
          requires:
            - librem_14

      - build:
          name: librem_15v4
          target: librem_15v4
          subcommand: ""
          requires:
            - librem_14

      - build:
          name: librem_mini
          target: librem_mini
          subcommand: ""
          requires:
            - librem_14

      - build:
          name: librem_mini_v2
          target: librem_mini_v2
          subcommand: ""
          requires:
            - librem_14

      - build:
          name: librem_11
          target: librem_11
          subcommand: ""
          requires:
            - librem_14

      # t480 is based on 24.12 coreboot release, not sharing any buildstack from now, depend on muscl-cross cache
      - build:
          name: t480-maximized
          target: t480-maximized
          subcommand: ""
          requires:
            - t480-hotp-maximized

      # dasharo release, share 24.02.01 utils/crossgcc
      - build:
          name: UNTESTED_nitropad-ns50
          target: UNTESTED_nitropad-ns50
          subcommand: ""
          requires:
            - novacustom-nv4x_adl

      #NovaCustom v56 boards are based on coreboot 24.02.01 fork, so depend on x230
      - build:
          name: novacustom-v560tu
          target: novacustom-v560tu
          subcommand: ""
          requires:
            - novacustom-nv4x_adl

      - build:
          name: novacustom-v540tu
          target: novacustom-v540tu
          subcommand: ""
          requires:
            - novacustom-nv4x_adl