#+TITLE: Clojure(script) CI

* Ci integration

Building a polylith based clojure project, these steps are similar to most clojure projects with a few additions for the poly tool.

* Github

** Deploy rules
Name our action and run it only when code is pushed into master
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
name: Staging Deploy
on:
  push:
    branches: [master]
#+END_SRC

** Checkout
Checkout repository, fetch depth is required if you needs tags available
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
     # Checkout the code
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0
#+END_SRC

** Cache
Cache the downloaded libraries so we don't do each each time.
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
      # Cache project dependencies
      - name: Cache deps
        uses: actions/cache@v2
        with:
          path: |
            ~/.polylith
            ~/.m2
            ~/.gitlibs
            ~/.clojure
          key: ${{ runner.os }}-maven-${{ hashFiles('deps.edn') }}
          restore-keys: |
            ${{ runner.os }}-maven-
            ${{ runner.os }}-
#+END_SRC

** Set env / project checks
Create a var called CHANGED_PROJECTS we can use in conditionals in later build steps,  we also check our project comply's to the polylith rules before moving onto linting, testing, building and deploying.
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
      # Check the project and set enc for later steps
      - name: Poly Check / Set Env
        run: |-
          cd workspace
          echo "CHANGED_PROJECTS=$(clojure -M:poly ws get:changes:changed-or-affected-projects since:previous-release skip:dev)" >> $GITHUB_ENV
          clojure -M:poly info since:release
          clojure -M:poly check
#+END_SRC


** Setup Java
Install a version on java using the java action.
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
      # Install java
      - name: Set up JDK & publish to maven
        uses: actions/setup-java@v1
        with:
          java-version: 13
#+END_SRC

** Setup clojure
Install clojure from the clojure action.
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
      # Install clojure
      - name: Install clojure tools
        uses: DeLaGuardo/setup-clojure@3.5
        with:
          cli: 1.10.3.933 
#+END_SRC

** Linting
Lint code with clj-kondo this example lints src and workspace folders.
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
      # Lint the code with kondo
      - name: Code Linting
        uses: DeLaGuardo/clojure-lint-action@master
        with:
          clj-kondo-args: --lint src workspace
          check-name: Linting
          github_token: ${{ secrets.GITHUB_TOKEN }}
#+END_SRC

** Testing changes since last release
Run test but only test since the last tagged release
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
    # Run the tests
    - name: Poly Test
      run: |-
        cd workspace
        clojure -M:poly test since:previous-release
#+END_SRC

** Building
Finally create your uberjar, this example uses a condition so it only builds if the projects or one of its components has changed.
We need to set the env in a previous step to make it available to future steps.
#+BEGIN_SRC yaml :tangle .github/workflows/example.yaml
    # Build the uberjar
    - name: Build my example api
      if: contains('${{ env.CHANGED_PROJECTS }}', 'my-example-api')
      run: |-
        cd  workspace/projects/my-example-api
        clojure -X:uberjar
#+END_SRC

** Deploying
