name: Build
on:
  pull_request:
  push:
    branches:
      - master
      - staging
      - trying
      - bors/staging
      - bors/trying

env:
  CARGO_TERM_COLOR: always

jobs:
  # Run cargo xtask format-check
  formatcheck:
    name: cargo fmt
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Fail on warnings
        run: find . -type f -name lib.rs -execdir sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' {} +

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: cargo xtask format-check
        run:  cargo xtask format-check

  # Compilation check
  check:
    name: check
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        backend:
          - thumbv7
          - thumbv6
          - thumbv8-base
          - thumbv8-main
        toolchain:
          - nightly
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install Rust ${{ matrix.toolchain }}
        run: |
          rustup override set ${{ matrix.toolchain }}

      - name: Configure Rust target (v6, v7, v8.b v8.m)
        run: |
          rustup target add thumbv7m-none-eabi
          rustup target add thumbv6m-none-eabi
          rustup target add thumbv8m.base-none-eabi
          rustup target add thumbv8m.main-none-eabi

      - name: Fail on warnings
        run: find . -type f -name lib.rs -execdir sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' {} +

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - run: cargo xtask --verbose --backend ${{ matrix.backend }} check 
  # Clippy
  clippy:
    name: clippy
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        backend:
          - thumbv7
          - thumbv6
          - thumbv8-base
          - thumbv8-main
        toolchain:
          - nightly
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install Rust ${{ matrix.toolchain }}
        run: |
          rustup override set ${{ matrix.toolchain }}

      - name: Configure Rust target (v6, v7, v8.b v8.m)
        run: |
          rustup target add thumbv7m-none-eabi
          rustup target add thumbv6m-none-eabi
          rustup target add thumbv8m.base-none-eabi
          rustup target add thumbv8m.main-none-eabi

      - name: Add Rust component clippy
        run: rustup component add clippy

      - name: Fail on warnings
        run: find . -type f -name lib.rs -execdir sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' {} +

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - run: cargo xtask --verbose --backend ${{ matrix.backend }} clippy

  # Verify all examples, checks
  checkexamples:
    name: check examples
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        backend:
          - thumbv7
          - thumbv6
          - thumbv8-base
          - thumbv8-main
        toolchain:
          - nightly
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install Rust ${{ matrix.toolchain }}
        run: |
          rustup override set ${{ matrix.toolchain }}

      - name: Configure Rust target (v6, v7, v8.b v8.m)
        run: |
          rustup target add thumbv7m-none-eabi
          rustup target add thumbv6m-none-eabi
          rustup target add thumbv8m.base-none-eabi
          rustup target add thumbv8m.main-none-eabi

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: Check the examples
        if: ${{ matrix.backend == 'thumbv8-base' }}
        run: cargo xtask --verbose --backend ${{ matrix.backend }} --exampleexclude pool example-check

      - name: Check the examples
        if: ${{ matrix.backend != 'thumbv8-base' }}
        run: cargo xtask --verbose --backend ${{ matrix.backend }} example-check

  # Verify the example output with run-pass tests
  testexamples:
    name: QEMU run
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        backend:
          - thumbv7
          - thumbv6
        toolchain:
          - nightly
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install Rust ${{ matrix.toolchain }}
        run: |
          rustup set profile minimal
          rustup override set ${{ matrix.toolchain }}

      - name: Configure Rust target (v6, v7)
        run: |
          rustup target add thumbv7m-none-eabi
          rustup target add thumbv6m-none-eabi

      - name: Add Rust component llvm-tools-preview
        run: rustup component add llvm-tools-preview

      # Use precompiled binutils
      - name: Install cargo-binutils
        uses: taiki-e/install-action@v2
        with:
          tool: cargo-binutils

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: Install QEMU
        run: |
          sudo apt update
          sudo apt install -y qemu-system-arm

      - name: Fail on warnings
        working-directory: ./rtic
        run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs

      - name: Run-pass tests
        run: cargo xtask --verbose --backend ${{ matrix.backend }} qemu 

  # Run test suite
  testsrtic:
    name: tests rtic
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        backend:
          - thumbv7-backend
          - thumbv6-backend
          - thumbv8base-backend
          - thumbv8main-backend

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: Fail on warnings
        working-directory: ./rtic
        run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs

      - name: Run cargo test
        working-directory: ./rtic
        run: cargo test --features ${{ matrix.backend }} --test ui

  # Run the macros test-suite
  testsmacros:
    name: tests rtic-macros
    runs-on: ubuntu-22.04
    strategy:
      matrix:
        backend:
          - cortex-m-source-masking
          - cortex-m-basepri

    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: Fail on warnings
        working-directory: ./rtic-macros
        run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs

      - name: cargo check
        working-directory: ./rtic-macros
        run: cargo test --features ${{ matrix.backend }} 

  # Run test suite
  testsarbiter:
    name: tests rtic-arbiter
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: Fail on warnings
        working-directory: ./rtic-arbiter
        run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs

      - name: Run cargo test
        working-directory: ./rtic-arbiter
        run: cargo test --features testing

  # Run test suite
  testschannel:
    name: tests rtic-channel
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: Fail on warnings
        working-directory: ./rtic-channel
        run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs

      - name: Run cargo test
        working-directory: ./rtic-channel
        run: cargo test --features testing

  # Run test suite
  testsmonotonics:
    name: tests rtic-monotonics
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: Fail on warnings
        working-directory: ./rtic-monotonics
        run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs

      - name: Run cargo test
        working-directory: ./rtic-monotonics
        run: cargo test --test tests

  # Run test suite
  teststime:
    name: tests rtic-time
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Cache Dependencies
        uses: Swatinem/rust-cache@v2

      - name: Fail on warnings
        working-directory: ./rtic-time
        run: sed -i 's,//deny_warnings_placeholder_for_ci,#![deny(warnings)],' src/lib.rs

      - name: Run cargo test
        working-directory: ./rtic-time
        run: cargo test

  # Build documentation, check links
  docs:
    name: build docs
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install lychee
        uses: taiki-e/install-action@v2
        with:
          tool: lychee

      - name: Remove cargo-config
        run: rm -f .cargo/config

      - name: Build docs
        # TODO: Any difference between backends?
        run: cargo doc --features thumbv7-backend

      - name: Check links
        run: |
          td=$(mktemp -d)
          cp -r target/doc $td/api
          lychee --offline --format detailed $td/api/rtic/
          lychee --offline --format detailed $td/api/rtic_macros/
          lychee --offline --format detailed $td/api/rtic_arbiter/
          lychee --offline --format detailed $td/api/rtic_channel/
          lychee --offline --format detailed $td/api/rtic_common/
          lychee --offline --format detailed $td/api/rtic_macros/
          lychee --offline --format detailed $td/api/rtic_monotonics/
          lychee --offline --format detailed $td/api/rtic_time/

  # Build the books
  mdbook:
    name: build mdbook
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Install lychee
        uses: taiki-e/install-action@v2
        with:
          tool: lychee

      - name: Install mdbook-mermaid
        uses: taiki-e/install-action@v2
        with:
          tool: mdbook-mermaid

      - name: mdBook Action
        uses: peaceiris/actions-mdbook@v1
        with:
          mdbook-version: 'latest'

      - name: Build book in English
        shell: 'script --return --quiet --command "bash {0}"'
        run: cd book/en && if mdbook build |& tee /dev/tty | grep "\[ERROR\]"; then exit 1; else exit 0; fi

      - name: Check links
        run: |
          td=$(mktemp -d)
          mkdir $td/book
          cp -r book/en/book $td/book/en
          cp LICENSE-* $td/book/en

          lychee --offline --format detailed $td/book/en/

#  # Update stable branch
#  #
#  # This needs to run before book is built
#  mergetostablebranch:
#    name: If CI passes, merge master branch into release/vX
#    runs-on: ubuntu-22.04
#    needs:
#      - style
#      - check
#      - clippy
#      - checkexamples
#      - testexamples
#      - checkmacros
#      - testmacros
#      - tests
#      - docs
#      - mdbook
#
#    # Only run this when pushing to master branch
#    if: github.ref == 'refs/heads/master'
#    steps:
#      - uses: actions/checkout@v3
#
#      - name: Get crate version and print output branch release/vX
#        id: crateversionbranch
#        # Parse metadata for version number, extract the Semver Major
#        run: |
#          VERSION=$(cargo metadata --format-version 1 --no-deps --offline | jq -r '.packages[] | select(.name =="cortex-m-rtic") | .version')
#          VERSIONMAJOR=${VERSION%.*.*}
#          echo "branch=release/v$VERSIONMAJOR" >> $GITHUB_ENV
#          echo "versionmajor=$VERSIONMAJOR" >> $GITHUB_ENV
#          echo "version=$VERSION" >> $GITHUB_ENV
#
#      - uses: everlytic/branch-merge@1.1.5
#        with:
#          github_token: ${{ github.token }}
#          source_ref: 'master'
#          target_branch: ${{ env.branch }}
#          commit_message_template: '[Bors] Merged {source_ref} into target {target_branch}'
#
#  # Only runs when pushing to master branch
#  # Bors run CI against staging branch,
#  # if that succeeds Borst tries against master branch
#  # If all tests pass, then deploy stage is run
#  deploy:
#    name: deploy
#    runs-on: ubuntu-22.04
#    needs:
#      mergetostablebranch
#
#    # Only run this when pushing to master branch
#    if: github.ref == 'refs/heads/master'
#    steps:
#      - uses: actions/checkout@v3
#
#     - name: Install lychee
#       uses: taiki-e/install-action@v2
#       with:
#         tool: lychee
#
#      - name: Install mdbook-mermaid
#        uses: taiki-e/install-action@v2
#        with:
#          tool: mdbook-mermaid
# 
#      - name: mdBook Action
#        uses: peaceiris/actions-mdbook@v1
#        with:
#          mdbook-version: 'latest'
#
#      - name: Get crate version
#        id: crateversion
#        # Parse metadata for version number, extract the Semver Major
#        run: |
#          VERSION=$(cargo metadata --format-version 1 --no-deps --offline | jq -r '.packages[] | select(.name =="cortex-m-rtic") | .version')
#          VERSIONMAJOR=${VERSION%.*.*}
#          echo "branch=release/v$VERSIONMAJOR" >> $GITHUB_ENV
#          echo "versionmajor=$VERSIONMAJOR" >> $GITHUB_ENV
#          echo "version=$VERSION" >> $GITHUB_ENV
#
#      - name: Remove cargo-config
#        run: rm -f .cargo/config
#
#      - name: Build docs
#        run: cargo doc
#
#      - name: Build books
#        shell: 'script --return --quiet --command "bash {0}"'
#        run: |
#          langs=( en )
#          devver=( dev )
#          # The latest stable must be the first element in the array
#          vers=( "1" "0.5" "0.4"  )
#
#          # All releases start with "v"
#          # followed by MAJOR.MINOR.PATCH, see semver.org
#          # Store first in array as stable
#          stable=${vers}
#          crateversion={{ env.versionmajor }}
#
#          echo "Latest stable version: $stable"
#          echo "Current crate version: $crateversion"
#
#          # Create directories
#          td=$(mktemp -d)
#          mkdir -p $td/$devver/book/
#          cp -r target/doc $td/$devver/api
#
#          # Redirect rtic.rs/meeting/index.html to hackmd
#          mkdir $td/meeting
#          sed "s|URL|https://hackmd.io/c_mFUZL-Q2C6614MlrrxOg|g" redirect.html > $td/meeting/index.html
#          sed -i "s|Page Redirection|RTIC Meeting|" $td/meeting/index.html
#          sed -i "s|If you|Redirecting to RTIC HackMD. If you|" $td/meeting/index.html
#
#          # Redirect the main site to the stable release
#          sed "s|URL|$stable|g" redirect.html > $td/index.html
#
#          # Create the redirects for dev-version
#          # If the current stable and the version being built differ,
#          # then there is a dev-version and the links should point to it.
#          if [[ "$stable" != "$crateversion" ]];
#          then
#            sed 's|URL|rtic/index.html|g' redirect.html > $td/$devver/api/index.html
#            sed 's|URL|book/en|g' redirect.html > $td/$devver/index.html
#          else
#            # If the current stable and the "dev" version in master branch
#            # share the same major version, redirect dev/ to stable book
#            sed 's|URL|rtic.rs/$stable/api/rtic|g' redirect.html > $td/$devver/api/index.html
#            sed 's|URL|rtic.rs/$stable|g' redirect.html > $td/$devver/index.html
#          fi
#
#          # Build books
#          for lang in ${langs[@]}; do
#              ( cd book/$lang &&
#                if mdbook build |& tee /dev/tty | grep "\[ERROR\]"; then exit 1; else exit 0; fi
#              )
#              cp -r book/$lang/book $td/$devver/book/$lang
#              cp LICENSE-* $td/$devver/book/$lang/
#          done
#
#          # Build older versions, including stable
#          root=$(pwd)
#          for ver in ${vers[@]}; do
#              prefix=${ver}
#
#              mkdir -p $td/$prefix/book
#              src=$(mktemp -d)
#              curl -L https://github.com/rtic-rs/cortex-m-rtic/archive/release/v${ver}.tar.gz | tar xz --strip-components 1 -C $src
#
#              pushd $src
#              rm -f .cargo/config
#              cargo doc --features thumbv7-backend || cargo doc --features thumbv7-backend,timer-queue
#              cp -r target/doc $td/$prefix/api
#              sed 's|URL|rtic/index.html|g' $root/redirect.html > $td/$prefix/api/index.html
#              for lang in ${langs[@]}; do
#                  ( cd book/$lang &&
#                    if mdbook build |& tee /dev/tty | grep "\[ERROR\]"; then exit 1; else exit 0; fi
#                  )
#                  cp -r book/$lang/book $td/$prefix/book/$lang
#                  cp LICENSE-* $td/$prefix/book/$lang/
#              done
#              sed 's|URL|book/en|g' $root/redirect.html > $td/$prefix/index.html
#              popd
#
#              rm -rf $src
#          done
#
#          # Copy the stable book to the stable alias
#          cp -r $td/$stable $td/stable
#
#          # Forward CNAME file
#          cp CNAME $td/
#          mv $td/ bookstodeploy
#
#      - name: Deploy to GH-pages
#        uses: peaceiris/actions-gh-pages@v3
#        with:
#          github_token: ${{ secrets.GITHUB_TOKEN }}
#          publish_dir: ./bookstodeploy
#          force_orphan: true

  # Refs: https://github.com/rust-lang/crater/blob/9ab6f9697c901c4a44025cf0a39b73ad5b37d198/.github/workflows/bors.yml#L125-L149
  #
  # ALL THE PREVIOUS JOBS NEEDS TO BE ADDED TO THE `needs` SECTION OF THIS JOB!

  ci-success:
    name: ci
    if: github.event_name == 'push' && success()
    needs:
      - formatcheck
      - check
      - clippy
      - checkexamples
      - testexamples
      - testsrtic
      - testsmacros
      - testsarbiter
      - testschannel
      - testsmonotonics
      - teststime
      - docs
      - mdbook
    runs-on: ubuntu-22.04
    steps:
      - name: Mark the job as a success
        run: exit 0