name: Docker Static

on:
  push:
    branches:
      - 'main'
  release:
    types:
      - 'published'
  pull_request:
    branches:
      - 'main'
  workflow_dispatch:
    inputs:
      msg:
        description: "Set message"
        default: "Manual trigger"

env:
  CARGO_TERM_COLOR: always


### CI Docs

# build-ui , create/compile the web
### install wasm
### install rollup
### run app/build.sh
### upload artifacts

# build-bin
## build-armhf, build-aarch64, build-amd64 , create binary for respective arch
#######################################################################################
# GitHub actions randomly timeout when downloading musl-gcc, using custom dev image   #
# Look into .github/workflows/Dockerfile.dev for development image details            #
# Using lldap dev image based on https://hub.docker.com/_/rust and musl-gcc bundled   #
#######################################################################################
### Cargo build
### aarch64 and amd64 is musl based
### armv7 is glibc based, musl had issue with time_t when cross compile https://github.com/rust-lang/libc/issues/1848

# build-ui,builds-armhf, build-aarch64, build-amd64 will upload artifacts will be used next job

# lldap-test
### will run lldap with postgres, mariadb and sqlite backend, do selfcheck command.

# Build docker image
### Triplet docker image arch with debian base
### amd64 & aarch64 with alpine base
# build-docker-image job will fetch artifacts and run Dockerfile.ci then push the image.
### Look into .github/workflows/Dockerfile.ci.debian or .github/workflowds/Dockerfile.ci.alpine

# create release artifacts
### Fetch artifacts
### Clean up web artifact
### Setup folder structure
### Compress
### Upload

# cache based on Cargo.lock per cargo target

jobs:
  build-ui:
    runs-on: ubuntu-latest
    container:
      image: nitnelave/rust-dev:latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3.3.0
      - uses: actions/cache@v3
        with:
          path: |
            /usr/local/cargo/bin
            /usr/local/cargo/registry/index
            /usr/local/cargo/registry/cache
            /usr/local/cargo/git/db
            target
          key: lldap-ui-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            lldap-ui-
      - name: Install rollup (nodejs)
        run: npm install -g rollup
      - name: Add wasm target (rust)
        run: rustup target add wasm32-unknown-unknown
      - name: Install wasm-pack with cargo
        run: cargo install wasm-pack || true
        env:
          RUSTFLAGS: ""
      - name: Build frontend
        run: ./app/build.sh
      - name: Check build path
        run: ls -al app/
      - name: Upload ui artifacts
        uses: actions/upload-artifact@v3
        with:
          name: ui
          path: app/


  build-bin:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        target: [armv7-unknown-linux-gnueabihf, aarch64-unknown-linux-musl, x86_64-unknown-linux-musl]
    container:
      image: nitnelave/rust-dev:latest
      env:
        CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER: arm-linux-gnueabihf-gcc
        CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_LINKER: aarch64-linux-musl-gcc
        CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER: x86_64-linux-musl-gcc
        CARGO_TERM_COLOR: always
        RUSTFLAGS: -Ctarget-feature=+crt-static
        CARGO_HOME: ${GITHUB_WORKSPACE}/.cargo
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3.3.0
      - uses: actions/cache@v3
        with:
          path: |
            .cargo/bin
            .cargo/registry/index
            .cargo/registry/cache
            .cargo/git/db
            target
          key: lldap-bin-${{ matrix.target }}-${{ hashFiles('**/Cargo.lock') }}
          restore-keys: |
            lldap-bin-${{ matrix.target }}-
      - name: Compile ${{ matrix.target }} lldap and migration tool
        run: cargo build --target=${{ matrix.target }} --release -p lldap -p migration-tool
      - name: Check path
        run: ls -al target/release
      - name: Upload ${{ matrix.target}} lldap artifacts
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.target}}-lldap-bin
          path: target/${{ matrix.target }}/release/lldap
      - name: Upload ${{ matrix.target }} migration tool artifacts
        uses: actions/upload-artifact@v3
        with:
          name: ${{ matrix.target }}-migration-tool-bin
          path: target/${{ matrix.target }}/release/migration-tool

  lldap-database-integration-test:
    needs: [build-ui,build-bin]
    name: LLDAP test
    runs-on: ubuntu-latest
    services:
        mariadb:
          image: mariadb:latest
          ports:
            - 3306:3306
          env:
            MYSQL_USER: lldapuser
            MYSQL_PASSWORD: lldappass
            MYSQL_DATABASE: lldap
            MYSQL_ROOT_PASSWORD: rootpass

        postgresql:
           image: postgres:latest
           ports:
             - 5432:5432
           env:
             POSTGRES_USER: lldapuser
             POSTGRES_PASSWORD: lldappass
             POSTGRES_DB: lldap

    steps:
       - name: Download artifacts
         uses: actions/download-artifact@v3
         with:
           name: x86_64-unknown-linux-musl-lldap-bin
           path: bin/
       - name: Where is the bin?
         run: ls -alR bin
       - name: Set executables to LLDAP
         run: chmod +x bin/lldap

       - name: Run lldap with postgres DB and healthcheck
         run: |
              bin/lldap run &
              sleep 10s
              bin/lldap healthcheck
         env:
           LLDAP_database_url: postgres://lldapuser:lldappass@localhost/lldap
           LLDAP_ldap_port: 3890
           LLDAP_http_port: 17170


       - name: Run lldap with mariadb DB (MySQL Compatible) and healthcheck
         run: |
              bin/lldap run &
              sleep 10s
              bin/lldap healthcheck
         env:
           LLDAP_database_url: mysql://lldapuser:lldappass@localhost/lldap
           LLDAP_ldap_port: 3891
           LLDAP_http_port: 17171


       - name: Run lldap with sqlite DB and healthcheck
         run: |
              bin/lldap run &
              sleep 10s
              bin/lldap healthcheck
         env:
           LLDAP_database_url: sqlite://users.db?mode=rwc
           LLDAP_ldap_port: 3892
           LLDAP_http_port: 17172


  build-docker-image:
    needs: [build-ui, build-bin]
    name: Build Docker image
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v3.3.0
      - name: Download all artifacts
        uses: actions/download-artifact@v3
        with:
          path: bin

      - name: Download llap ui artifacts
        uses: actions/download-artifact@v3
        with:
          name: ui
          path: web

      - name: Setup QEMU
        uses: docker/setup-qemu-action@v2
      - uses: docker/setup-buildx-action@v2

      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          # list of Docker images to use as base name for tags
          images: |
            nitnelave/lldap
          # generate Docker tags based on the following events/attributes
          tags: |
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=semver,pattern={{major}}
            type=sha

      - name: parse tag
        uses: gacts/github-slug@v1
        id: slug

      - name: Login to Docker Hub
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

########################################
#### docker image :latest tag build ####
########################################
      - name: Build and push latest alpine
        if: github.event_name != 'release'
        uses: docker/build-push-action@v4
        with:
          context: .
          push: ${{ github.event_name != 'pull_request' }}
          platforms: linux/amd64,linux/arm64
          file: ./.github/workflows/Dockerfile.ci.alpine
          tags: nitnelave/lldap:latest, nitnelave/lldap:latest-alpine
          cache-from: type=gha,mode=max
          cache-to: type=gha,mode=max

      - name: Build and push latest debian
        if: github.event_name != 'release'
        uses: docker/build-push-action@v4
        with:
          context: .
          push: ${{ github.event_name != 'pull_request' }}
          platforms: linux/amd64,linux/arm64,linux/arm/v7
          file: ./.github/workflows/Dockerfile.ci.debian
          tags: nitnelave/lldap:latest-debian
          cache-from: type=gha,mode=max
          cache-to: type=gha,mode=max

########################################
#### docker image :semver tag build ####
########################################
      - name: Build and push release alpine
        if: github.event_name == 'release'
        uses: docker/build-push-action@v4
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          # Tag as latest, stable, semver, major, major.minor and major.minor.patch.
          file: ./.github/workflows/Dockerfile.ci.alpine
          tags: nitnelave/lldap:stable, nitnelave/lldap:stable-alpine, nitnelave/lldap:v${{ steps.slug.outputs.version-semantic }}, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}.${{ steps.slug.outputs.version-patch }}, nitnelave/lldap:v${{ steps.slug.outputs.version-semantic }}-alpine, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}-alpine, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}-alpine.${{ steps.slug.outputs.version-minor }}-alpine, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}.${{ steps.slug.outputs.version-patch }}-alpine
          cache-from: type=gha,mode=max
          cache-to: type=gha,mode=max

      - name: Build and push release debian
        if: github.event_name == 'release'
        uses: docker/build-push-action@v4
        with:
          context: .
          platforms: linux/amd64,linux/arm64,linux/arm/v7
          push: true
          # Tag as latest, stable, semver, major, major.minor and major.minor.patch.
          file: ./.github/workflows/Dockerfile.ci.debian
          tags: nitnelave/lldap:stable-debian, nitnelave/lldap:v${{ steps.slug.outputs.version-semantic }}-debian, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}-debian, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}-debian, nitnelave/lldap:v${{ steps.slug.outputs.version-major }}.${{ steps.slug.outputs.version-minor }}.${{ steps.slug.outputs.version-patch }}-debian
          cache-from: type=gha,mode=max
          cache-to: type=gha,mode=max

      - name: Update repo description
        if: github.event_name != 'pull_request'
        uses: peter-evans/dockerhub-description@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_PASSWORD }}
          repository: nitnelave/lldap

###############################################################
### Download artifacts, clean up ui, upload to release page ###
###############################################################
  create-release-artifacts:
     needs: [build-ui, build-bin]
     name: Create release artifacts
     if: github.event_name == 'release'
     runs-on: ubuntu-latest
     steps:
      - name: Download all artifacts
        uses: actions/download-artifact@v3
        with:
          path: bin/
      - name: Check file
        run: ls -alR bin/
      - name: Fixing Filename
        run: |
             mv bin/aarch64-unknown-linux-musl-lldap-bin/lldap bin/aarch64-lldap
             mv bin/x86_64-unknown-linux-musl-lldap-bin/lldap bin/amd64-lldap
             mv bin/armv7-unknown-linux-gnueabihf-lldap-bin/lldap bin/armhf-lldap
             mv bin/aarch64-unknown-linux-musl-migration-tool-bin/migration-tool bin/aarch64-migration-tool
             mv bin/x86_64-unknown-linux-musl-migration-tool-bin/migration-tool bin/amd64-migration-tool
             mv bin/armv7-unknown-linux-gnueabihf-migration-tool-bin/migration-tool bin/armhf-migration-tool
             chmod +x bin/*-lldap
             chmod +x bin/*-migration-tool

      - name: Download llap ui artifacts
        uses: actions/download-artifact@v3
        with:
          name: ui
          path: web
      - name: UI (web) artifacts cleanup
        run: mkdir app && mv web/index.html app/index.html && mv web/static app/static && mv web/pkg app/pkg
      - name: Fetch web components
        run: |
             sudo apt update
             sudo apt install wget
             for file in $(cat app/static/libraries.txt); do wget -P app/static "$file"; done
             for file in $(cat app/static/fonts/fonts.txt); do wget -P app/static/fonts "$file"; done
             chmod a+r -R .

      - name: Setup LLDAP dir for packing
        run: |
             mkdir aarch64-lldap
             mkdir amd64-lldap
             mkdir armhf-lldap
             mv bin/aarch64-lldap aarch64-lldap/lldap
             mv bin/amd64-lldap amd64-lldap/lldap
             mv bin/armhf-lldap armhf-lldap/lldap
             mv bin/aarch64-migration-tool aarch64-lldap/migration-tool
             mv bin/amd64-migration-tool amd64-lldap/migration-tool
             mv bin/armhf-migration-tool armhf-lldap/migration-tool
             cp -r app aarch64-lldap/
             cp -r app amd64-lldap/
             cp -r app armhf-lldap/
             ls -alR aarch64-lldap/
             ls -alR amd64-lldap/
             ls -alR armhf-lldap/

      - name: Packing LLDAP and Web UI
        run: |
             tar -czvf aarch64-lldap.tar.gz aarch64-lldap/
             tar -czvf amd64-lldap.tar.gz amd64-lldap/
             tar -czvf armhf-lldap.tar.gz armhf-lldap/


      - name: Upload compressed release
        uses: ncipollo/release-action@v1
        id: create_release
        with:
          allowUpdates: true
          artifacts:  aarch64-lldap.tar.gz,
                      amd64-lldap.tar.gz,
                      armhf-lldap.tar.gz
        env:
         GITHUB_TOKEN: ${{ github.token }}
