Link to repository: github.com/zysktomasz/spotify-randomizer
Overview
SpotifyRandomizer Backend - handles authenticated communication with Spotify API.
Exposes a few REST endpoints that can be used by clients (such as SpotifyRandomizer React Client) to invoke such actions as: retrieving authenticated user details, their playlists and songs, as well as a way to automatically reorganize order of songs in selected playlists.
Technologies used
- Java 16
- Spring Boot 2.4.x
- Docker
- Spotify Client (github.com/thelinmichael/spotify-web-api-java)
- Jjwt (github.com/jwtk/jjwt)
- MapStruct, Lombok
- Google Cloud Config (Runtime environments) (github.com/GoogleCloudPlatform/spring-cloud-gcp)
- Github Actions
- GCP Cloud Build, Cloud Run, Artifact Registry
Architecture

Rest API
Application exposes a few API endpoints. It allows to:
- GET /api/spotify/playlist- get user playlists
- GET /api/spotify/playlist/{playlistId}/tracks- get playlist tracks
- PUT /api/spotify/playlist/{playlistId}- reorder songs in playlists
Authentication
Application follows Authorization Code Flow described in Spotify Authorization Guide to authenticate user.
Authentication is done by communication between backend (this project) and Spotify API through usage of thelinmichael/spotify-web-api-java.
This application secures its endpoints by JWT.
Docker
Application is dockerized.
Deployment
Docker image is built and deployed to Google Cloud Run.
Cloud Run is scaled to 0 - meaning that it is turned off when not in use and requires little time to spin up when invoked.
Entire process of image building and deployment is handled by Google Cloud Build and described later in this document.
Google Cloud Runtime Config Environments Configuration
To avoid storing sensitive information, like API secrets a number of application properties set in application.yml
files are bootstrapped from Google Cloud Runtime Config
environments. To access and manage them one has to have Cloud SDK installed with beta runtime-config added.
Spring Cloud Google Cloud Config project is used to achieve this functionality. It allows for application to load these properties from GCP environment during startup.
Continuous Integration & Continuous Deployment
Github Actions are used to achieve CI/CD. Actions are configured
in github-ci.yml
Steps done during CI:
- Install Java SDK on Ubuntu 20.04
- Load cached maven packages (if available) from previous builds, to speed up process
- Run tests and build reports (by running mvn site)
- Verify output of previous step (mvn verify)
- Upload reports as Github artifacts - makes it possible to download and analyze
Steps done during CD:
- Check condition to confirm that master branch can run deployment job.
- Configure Cloud SDK with credentials stored in Github Secrets
- Build and push Docker image to Google Artifact Registry
- Deploy image to Cloud Run
name: Java Maven CI
on: [ push ]
env:
  PROJECT_ID: ${{ secrets.GCP_PROJECT_ID }}
  SERVICE_ACCOUNT_KEY: ${{ secrets.GCP_SA_KEY }}
  ARTIFACT_REPOSITORY_NAME: spotifyrandomizer-repo
  SERVICE: spotifyrandomizer-backend
  REGION: europe-central2
jobs:
  test_and_build_reports:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2
      - run: |
          download_url="https://github.com/AdoptOpenJDK/openjdk16-binaries/releases/download/jdk-16.0.1%2B9/OpenJDK16U-jdk_x64_linux_hotspot_16.0.1_9.tar.gz"
          wget -O $RUNNER_TEMP/java_package.tar.gz $download_url
      - name: Set up JDK 16
        uses: actions/setup-java@v2
        with:
          distribution: 'jdkfile'
          jdkFile: ${{ runner.temp }}/java_package.tar.gz
          java-version: '16.0.1'
          architecture: x64
      - name: Cache Maven packages
        uses: actions/cache@v2
        with:
          path: ~/.m2
          key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
          restore-keys: ${{ runner.os }}-m2
      - name: mvn site - build reports
        run: mvn site
      - name: mvn verify
        run: mvn verify
      - name: Archive project reports (tests and coverage)
        uses: actions/upload-artifact@v2
        with:
          name: reports
          path: target/site
  build_and_release:
    if: ${{ github.ref == 'refs/heads/master' }}
    needs: test_and_build_reports
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2
      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@master
        with:
          project_id: ${{ env.PROJECT_ID }}
          service_account_key: ${{ env.SERVICE_ACCOUNT_KEY }}
          export_default_credentials: true
      - name: Authorize Docker push
        run: gcloud auth configure-docker europe-central2-docker.pkg.dev
      - name: Build and push to Artifact Registry
        run: |-
          docker build -t europe-central2-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.ARTIFACT_REPOSITORY_NAME }}/${{ env.SERVICE }}:${{ github.sha }} .
          docker push europe-central2-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.ARTIFACT_REPOSITORY_NAME }}/${{ env.SERVICE }}:${{ github.sha }}
      - name: Deploy to Cloud Run
        run: |-
          gcloud run deploy ${{ env.SERVICE }} \
            --region ${{ env.REGION }} \
            --image europe-central2-docker.pkg.dev/${{ env.PROJECT_ID }}/${{ env.ARTIFACT_REPOSITORY_NAME }}/${{ env.SERVICE }}:${{ github.sha }} \
            --platform "managed" \
