- name: eval-haskell
  hosts: eval-haskell.fi.muni.cz
  vars:
    dhcpcd: false
    postfix: true
    ghc_version: 9.2.1
    ghc_version_bootstrap: 9.0.2
    cabal_version: 3.6.2.0
    ghc_prefix: '/opt/ghc/{{ghc_version}}'
    cabal_dir: '/usr/local/bin'
    ib015_workers: 8
    ib016_workers: 2
    backports: false
    frag_eval_tools:
      - auto
      - cc
      - group
      - sandbox
      - sub

  tasks:
    - import_role:
        name: runner_install
      tags:
        - install

    - block:
      - import_role:
          name: common_deb

      - name: Install frag requisites
        apt:
          pkg:
            - darcs
            - clang
            - libcurl4-gnutls-dev
            - libexpat1-dev
            - libldap2-dev
            - libacl1-dev
            - libcap-dev

      - name: Postgres key
        apt_key:
          data: |
            -----BEGIN PGP PUBLIC KEY BLOCK-----

[encoded data, 5544 characters]
            Gtz3cydIohvNO9d90+29h0eGEDYti7j7maHkBKUAwlcPvMg5m3Y=
            =DA1T
            -----END PGP PUBLIC KEY BLOCK-----


      - name: Postgres repo
        apt_repository:
          repo: deb http://apt.postgresql.org/pub/repos/apt bullseye-pgdg main
          filename: postgres

      - name: Postgres
        apt:
          pkg:
            - postgresql-client-12
            - libpq-dev
          default_release: bullseye-pgdg


      - name: Frag dir
        file:
          state: directory
          path: /var/frag
          owner: root
          group: systemd-journal
          mode: 02755

      - name: frag checkout exits?
        stat:
           path: /var/frag/frag/_darcs
        register: frag_chekout

      - name: Checkout frag
        command:
          chdir: /var/frag
          cmd: darcs get https://paradise.fi.muni.cz/~xstill/src/frag/
        when: not frag_chekout.stat.exists

      - name: Update frag darcs
        command:
          chdir: /var/frag/frag
          cmd: 'darcs pull -a'

      - name: "Gib config for frag"
        copy:
          src: frag/gib.local
          dest: /var/frag/frag/gib/local

      - name: Update frag build
        command:
          chdir: /var/frag/frag
          cmd: make

      - name: Builder user
        user:
          name: builder
          create_home: True
          shell: /bin/bash
          system: True

      - name: GHC requisites
        apt:
          pkg:
            - libtinfo-dev
            - libtinfo5
            - libgmp-dev
            - libgmp10

      - name: GHC target dir
        file:
          state: directory
          path: '{{ghc_prefix}}'

      - name: GHC installed?
        stat:
           path: '/opt/ghc/{{ghc_version}}/bin/ghc'
        register: ghc_bin

      - block:
          - name: GHC bootstrap directory
            file: 
              state: directory
              path: /home/builder/ghc-bootstrap

          - name: Download GHC bootstrap
            get_url:
              url: 'https://downloads.haskell.org/~ghc/{{ghc_version_bootstrap}}/ghc-{{ghc_version_bootstrap}}-x86_64-deb9-linux.tar.xz'
              dest: /home/builder/ghc-bootstrap/ghc.tar.xz

          - name: Extract GHC bootstrap
            unarchive:
              src: /home/builder/ghc-bootstrap/ghc.tar.xz
              dest: /home/builder/ghc-bootstrap/
              remote_src: True

          - name: Build GHC bootstrap
            shell:
              chdir: '/home/builder/ghc-bootstrap/ghc-{{ghc_version_bootstrap}}'
              cmd: '{{item}}'
            loop:
              - './configure --prefix=/home/builder/ghc-bootstrap'
              - make install -j8

          - name: Download GHC
            get_url:
              url: 'https://downloads.haskell.org/~ghc/{{ghc_version}}/ghc-{{ghc_version}}-src.tar.xz'
              dest: /home/builder/ghc.tar.xz

          - name: Extract GHC
            unarchive:
              src: /home/builder/ghc.tar.xz
              dest: /home/builder/
              remote_src: True

          - name: Build GHC
            shell:
              chdir: '/home/builder/ghc-{{ghc_version}}'
              cmd: 'env LANG=en_US.UTF-8 PATH=/home/builder/ghc-bootstrap/bin:$PATH {{item}}'
            loop:
              - ./boot
              - './configure --prefix={{ghc_prefix}} --disable-large-address-space --with-system-libffi --with-ffi-includes=$(pkg-config --variable=includedir libffi)'
              - make -j8

        become_user: builder
        become: true
        when: not ghc_bin.stat.exists

      - name: Install ghc
        shell:
          chdir: '/home/builder/ghc-{{ghc_version}}'
          cmd: 'env LANG=en_US.UTF-8 {{item}}'
        loop:
          - make install
        when: not ghc_bin.stat.exists

      - name: Symlink GHC to /usr/local/bin
        file:
          src: '/opt/ghc/{{ghc_version}}/bin/{{item}}'
          dest: '/usr/local/bin/{{item}}'
          state: link
        loop:
          - 'ghc'
          - 'ghc-{{ghc_version}}'
          - 'ghc-pkg'
          - 'ghc-pkg-{{ghc_version}}'
          - 'ghci'
          - 'ghci-{{ghc_version}}'
          - 'haddock'
          - 'haddock-ghc-{{ghc_version}}'
          - 'hp2ps'
          - 'hpc'
          - 'hsc2hs'
          - 'runghc'
          - 'runghc-{{ghc_version}}'
          - 'runhaskell'

      - name: IB015 eval users
        user:
          name: 'ib015_eval_{{item}}'
          create_home: True
          home: '/var/frag/ib015_eval_{{item}}/'
          shell: /bin/bash
          system: True
        loop: '{{range(ib015_workers)}}'

      - name: IB015 evals' env
        copy:
          content: |
            FRAG_SUBJECT=ib015
            FRAG_HOST=frag-db.fi.muni.cz
          dest: '/var/frag/ib015_eval_{{item}}/env'
        loop: '{{range(ib015_workers)}}'

      - name: IB015 evals' progs
        copy:
          src: '/var/frag/frag/_build/eval-{{item[1]}}'
          dest: '/var/frag/ib015_eval_{{item[0]}}/{{item[1]}}'
          remote_src: True
          mode: 0555
        loop: '{{range(ib015_workers) | product(frag_eval_tools) | list}}'
        register: ib015_ev_progs

      - name: IB015 eval deamons
        copy:
          src: '/var/frag/frag/_build/frag-eval'
          dest: '/var/frag/ib015_eval_{{item}}/'
          remote_src: true
          mode: 0555
        loop: '{{range(ib015_workers)}}'
        register: ib015_eval

      - name: Eval service
        get_url:
          url: https://gitlab.fi.muni.cz/xstill/frag-utils/-/raw/master/systemd/frag-eval@.service
          dest: /etc/systemd/system/frag-eval@.service
        register: eval_service

      - name: Enable IB015 evals
        systemd:
          name: 'frag-eval@ib015_eval_{{item}}'
          enabled: true
          state: '{{"re" if ib015_eval.changed or ib015_ev_progs.changed else ""}}started'
          daemon_reload: '{{eval_service.changed}}'
        loop: '{{range(ib015_workers)}}'

      - name: Add cabal
        unarchive:
          src: "https://downloads.haskell.org/~cabal/cabal-install-{{cabal_version}}/cabal-install-{{cabal_version}}-x86_64-linux-deb10.tar.xz"
          dest: "{{cabal_dir}}"
          remote_src: true

      - name: .cabal exits?
        stat:
          path: '/var/frag/ib015_eval_{{item}}/.cabal'
        loop: '{{range(ib015_workers)}}'
        register: dot_cabal_ib015

      - name: Cabal update
        command: "{{cabal_dir}}/cabal v2-update"
        become: True
        become_user: 'ib015_eval_{{item}}'
#        when: not dot_cabal_ib015.results[item].stat.exists
        when: false
        loop: '{{range(ib015_workers)}}'

      - name: Create empty GHC env file
        copy:
          content: ""
          dest: '/tmp/env.ib015.{{item}}'
          owner: 'ib015_eval_{{item}}'
        loop: '{{range(ib015_workers)}}'


      - name: Hackage modules
        command: "{{cabal_dir}}/cabal v2-install --lib --package-env=/tmp/env.ib015.{{item}} QuickCheck lens HUnit graph-wrapper data-default-class mtl exceptions-0.10.4"
        become: True
        become_user: 'ib015_eval_{{item}}'
        loop: '{{range(ib015_workers)}}'

      - name: hsExprTest checkout
        git:
          dest: '/var/frag/ib015_eval_{{item}}/hsExprTest'
          repo: https://github.com/vlstill/hsExprTest.git
          update: True
        become: True
        become_user: 'ib015_eval_{{item}}'
        loop: '{{range(ib015_workers)}}'

      - name: Install hsExprTest
        command:
          chdir: '/var/frag/ib015_eval_{{item}}/hsExprTest/'
          cmd: "{{cabal_dir}}/cabal v2-install --lib --package-env=/tmp/env.ib015.{{item}} "
        become: True
        become_user: 'ib015_eval_{{item}}'
        loop: '{{range(ib015_workers)}}'

      - name: Create GHC environment dir
        file:
          state: directory
          path: "~/.local/share/ghc/x86_64-linux-{{ghc_version}}/environments"
        become: True
        become_user: 'ib015_eval_{{item}}'
        loop: '{{range(ib015_workers)}}'

      - name: Deploy modified GHC environment
        command: "mv /tmp/env.ib015.{{item}} ~/.local/share/ghc/x86_64-linux-{{ghc_version}}/environments/default"
        become: True
        become_user: 'ib015_eval_{{item}}'
        loop: '{{range(ib015_workers)}}'

      # TODO: deduplicate
      - name: IB016 evals' progs
        copy:
          src: '/var/frag/frag/_build/eval-{{item[1]}}'
          dest: '/var/frag/ib016_eval_{{item[0]}}/{{item[1]}}'
          remote_src: true
          mode: 0555
        loop: '{{range(ib016_workers) | product(frag_eval_tools) | list}}'
        register: ib016_ev_progs

      - name: IB016 eval deamons
        copy:
          src: '/var/frag/frag/_build/frag-eval'
          dest: '/var/frag/ib016_eval_{{item}}/'
          remote_src: true
          mode: 0555
        loop: '{{range(ib016_workers)}}'
        register: ib016_eval

      - name: Enable IB016 evals
        systemd:
          name: 'frag-eval@ib016_eval_{{item}}'
          enabled: true
          state: '{{"re" if ib016_eval.changed or ib016_ev_progs.changed else ""}}started'
          daemon_reload: '{{eval_service.changed}}'
        loop: '{{range(ib016_workers)}}'

      - name: .cabal exits?
        stat:
          path: '/var/frag/ib016_eval_{{item}}/.cabal'
        loop: '{{range(ib016_workers)}}'
        register: dot_cabal_ib016

      - name: Cabal update
        command: "{{cabal_dir}}/cabal v2-update"
        become: True
        become_user: 'ib016_eval_{{item}}'
        # when: not dot_cabal_ib016.results[item].stat.exists
        loop: '{{range(ib016_workers)}}'

      - name: Remove stale GHC environments
        file:
          path: "/tmp/env.ib016.{{item}}"
          state: absent
        loop: '{{range(ib016_workers)}}'

      - name: Remove GHC environemnt from ~/.ghc
        file:
          path: "~/.ghc/x86_64-linux-9.2.1/environments/default"
          state: absent
        become: true
        become_user: 'ib016_eval_{{item}}'
        loop: '{{range(ib016_workers)}}'

      - name: Hackage modules
        command: "{{cabal_dir}}/cabal v2-install --lib --package-env=/tmp/env.ib016.{{item}} QuickCheck lens mtl exceptions base-unicode-symbols data-default-class HUnit"
        become: True
        become_user: 'ib016_eval_{{item}}'
        loop: '{{range(ib016_workers)}}'

      - name: Install parsec last, it is broken somehow otherwise
        command: "{{cabal_dir}}/cabal v2-install --lib --package-env=/tmp/env.ib016.{{item}} parsec"
        become: True
        become_user: 'ib016_eval_{{item}}'
        loop: '{{range(ib016_workers)}}'

      - name: hsExprTest checkout
        git:
          dest: '/var/frag/ib016_eval_{{item}}/hsExprTest'
          repo: https://github.com/vlstill/hsExprTest.git
          update: True
        become: True
        become_user: 'ib016_eval_{{item}}'
        loop: '{{range(ib016_workers)}}'

      - name: Install hsExprTest
        command:
          chdir: '/var/frag/ib016_eval_{{item}}/hsExprTest/'
          cmd: "{{cabal_dir}}/cabal v2-install --lib --package-env=/tmp/env.ib016.{{item}}"
        become: True
        become_user: 'ib016_eval_{{item}}'
        loop: '{{range(ib016_workers)}}'

      - name: Create GHC environment dir
        file:
          state: directory
          path: "~/.local/share/ghc/x86_64-linux-{{ghc_version}}/environments"
        become: True
        become_user: 'ib016_eval_{{item}}'
        loop: '{{range(ib016_workers)}}'

      - name: Deploy modified GHC environment
        command: "mv /tmp/env.ib016.{{item}} ~/.local/share/ghc/x86_64-linux-{{ghc_version}}/environments/default"
        become: True
        become_user: 'ib016_eval_{{item}}'
        loop: '{{range(ib016_workers)}}'

      - name: Enable user namespaces
        sysctl:
          name: kernel.unprivileged_userns_clone
          value: "1"
          state: present
          reload: yes

      tags:
        - deploy

# vim: shiftwidth=2 tabstop=2 softtabstop=2 ft=yaml.ansible
