name: Appsmith Github Release Workflow

# This workflow builds Docker images for server and client, and then pushes them to Docker Hub.
# The docker-tag with which this push happens is the release tag (e.g., v1.2.3 etc.).
# In addition to the above tag, unless the git-tag matches `*beta*`, we also push to the `latest` docker-tag.
# This workflow does NOT run tests.
# This workflow is automatically triggered when a release is created on GitHub.

on:
  # Ref: <https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows#release>.
  release:
    types:
      # Unlike the `released` event, the `published` event triggers for pre-releases as well.
      - released

jobs:
  prelude:
    runs-on: ubuntu-latest

    outputs:
      tag: ${{ steps.get_version.outputs.tag }}
      is_beta: ${{ steps.get_version.outputs.is_beta }}

    steps:
      - name: Environment details
        run: |
          echo "PWD: $PWD"
          echo "GITHUB_REF: $GITHUB_REF"
          echo "GITHUB_SHA: $GITHUB_SHA"
          echo "GITHUB_EVENT_NAME: $GITHUB_EVENT_NAME"

      - name: Get the version
        id: get_version
        run: |
          tag="${GITHUB_REF#refs/tags/}"
          echo "::set-output name=tag::$tag"
          if [[ $tag == *"beta"* ]]; then
            echo "::set-output name=is_beta::true"
          else
            echo "::set-output name=is_beta::false"
          fi

  buildClient:
    needs:
      - prelude

    runs-on: ubuntu-latest

    defaults:
      run:
        working-directory: app/client
        shell: bash

    steps:
      # Checkout the code
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Use Node.js 14.15.4
        uses: actions/setup-node@v1
        with:
          node-version: "14.15.4"

      # Retrieve npm dependencies from cache. After a successful run, these dependencies are cached again
      - name: Cache npm dependencies
        uses: actions/cache@v2
        env:
          cache-name: cache-yarn-dependencies
        with:
          # npm dependencies are stored in `~/.m2` on Linux/macOS
          path: ~/.npm
          key: ${{ runner.OS }}-node-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.OS }}-node-
            ${{ runner.OS }}-

      - name: Install dependencies
        run: yarn install

      - name: Create the bundle
        env:
          REACT_APP_ENVIRONMENT: "PRODUCTION"
          REACT_APP_FUSIONCHARTS_LICENSE_KEY: "${{ secrets.APPSMITH_FUSIONCHARTS_LICENSE_KEY }}"
          REACT_APP_SEGMENT_CE_KEY: "${{ secrets.APPSMITH_SEGMENT_CE_KEY }}"
          REACT_APP_VERSION_ID: "${{ needs.prelude.outputs.tag }}"
          REACT_APP_INTERCOM_APP_ID: "${{ secrets.APPSMITH_INTERCOM_ID }}"
        run: |
          REACT_APP_VERSION_RELEASE_DATE="$(date -u '+%Y-%m-%dT%H:%M:%SZ')" \
            yarn build
          ls -l build

      # Upload the build artifact so that it can be used by the test & deploy job in the workflow
      - name: Upload react build bundle
        uses: actions/upload-artifact@v2
        with:
          name: client-build
          path: app/client/build/

  buildServer:
    needs:
      - prelude

    defaults:
      run:
        working-directory: app/server

    runs-on: ubuntu-latest

    steps:
      - name: Checkout the code
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Set up JDK 1.11
        uses: actions/setup-java@v1
        with:
          java-version: "11.0.10"

      # Retrieve maven dependencies from cache. After a successful run, these dependencies are cached again
      - name: Cache maven dependencies
        uses: actions/cache@v2
        env:
          cache-name: cache-maven-dependencies
        with:
          # maven dependencies are stored in `~/.m2` on Linux/macOS
          path: ~/.m2
          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
          restore-keys: ${{ runner.os }}-m2

      - name: Test and Build package
        working-directory: app/server
        run: |
          mvn --batch-mode versions:set \
            -DnewVersion=${{ needs.prelude.outputs.tag }} \
            -DgenerateBackupPoms=false \
            -DprocessAllModules=true
          ./build.sh -DskipTests
          ls -l dist

      - name: Upload server build bundle
        uses: actions/upload-artifact@v2
        with:
          name: server-build
          path: app/server/dist/

  buildRts:
    needs:
      - prelude

    defaults:
      run:
        working-directory: app/rts

    runs-on: ubuntu-latest

    steps:
      # Checkout the code
      - uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: Use Node.js 14.15.4
        uses: actions/setup-node@v1
        with:
          node-version: "14.15.4"

      - name: Build
        run: |
          echo 'export const VERSION = "${{ needs.prelude.outputs.tag }}"' > src/version.js
          ./build.sh
          ls -l dist

      # Upload the build artifact so that it can be used by the test & deploy job in the workflow
      - name: Upload RTS build bundle
        uses: actions/upload-artifact@v2
        with:
          name: rts-build
          path: app/rts/dist/

      - name: Upload RTS dependencies bundle
        uses: actions/upload-artifact@v2
        with:
          name: rts-build-deps
          path: app/rts/node_modules/

  package:
    needs: [prelude, buildClient, buildServer, buildRts]

    runs-on: ubuntu-latest

    steps:
      - name: Checkout the merged commit from PR and base branch
        uses: actions/checkout@v2

      - name: Download the client build artifact
        uses: actions/download-artifact@v2
        with:
          name: client-build
          path: app/client/build

      - name: Download the server build artifact
        uses: actions/download-artifact@v2
        with:
          name: server-build
          path: app/server/dist

      - name: Download the rts build artifact
        uses: actions/download-artifact@v2
        with:
          name: rts-build
          path: app/rts/dist

      - name: Download the rts dependencies artifact
        uses: actions/download-artifact@v2
        with:
          name: rts-build-deps
          path: app/rts/node_modules/

      - name: Set up QEMU (needed for docker buildx)
        uses: docker/setup-qemu-action@v1

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

      - name: Build and push client image
        working-directory: app/client
        run: |
          docker build -t ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-editor:${{needs.prelude.outputs.tag}} .
          docker push ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-editor:${{needs.prelude.outputs.tag}}

          # Only build & tag with latest if the tag doesn't contain beta
          if [[ ! ${{needs.prelude.outputs.tag}} == *"beta"* ]]; then
            docker build -t ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-editor:latest .
            docker push ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-editor:latest
          fi

      - name: Build and push fat image
        run: |
          tag_args="--tag ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-ce:${{needs.prelude.outputs.tag}}"

          # Only build & tag with latest if the tag doesn't contain beta
          if [[ ! ${{needs.prelude.outputs.tag}} == *"beta"* ]]; then
            tag_args="$tag_args --tag ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-ce:latest"
          fi

          docker buildx build \
            --platform linux/arm64,linux/amd64 \
            --push \
            --build-arg APPSMITH_SEGMENT_CE_KEY=${{ secrets.APPSMITH_SEGMENT_CE_KEY }} \
            $tag_args \
            .

      - name: Build and push server image
        working-directory: app/server
        run: |
          docker build --build-arg APPSMITH_SEGMENT_CE_KEY=${{ secrets.APPSMITH_SEGMENT_CE_KEY }} -t ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-server:${{needs.prelude.outputs.tag}} .
          docker push ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-server:${{needs.prelude.outputs.tag}}

          # Only build & tag with latest if the tag doesn't contain beta
          if [[ ! ${{needs.prelude.outputs.tag}} == *"beta"* ]]; then
            docker build --build-arg APPSMITH_SEGMENT_CE_KEY=${{ secrets.APPSMITH_SEGMENT_CE_KEY }} -t ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-server:latest .
            docker push ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-server:latest
          fi

      - name: Build and push RTS image
        working-directory: app/rts
        run: |
          docker build -t ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-rts:${{needs.prelude.outputs.tag}} .
          docker push ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-rts:${{needs.prelude.outputs.tag}}

          # Only build & tag with latest if the tag doesn't contain beta
          if [[ ! ${{needs.prelude.outputs.tag}} == *"beta"* ]]; then
            docker build -t ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-rts:latest .
            docker push ${{ secrets.DOCKER_HUB_ORGANIZATION }}/appsmith-rts:latest
          fi
