DEV Community

Cover image for Automate Spotify and YouTube Playlists - Chapter 6: Deployment
Tawanda Nyahuye
Tawanda Nyahuye

Posted on

Automate Spotify and YouTube Playlists - Chapter 6: Deployment

The script works on your computer. But your computer isn't always on, and "remember to run this manually every day" defeats the whole point.

In this chapter, we push the code to GitHub and set up a GitHub Action — a free, scheduled job that runs the script every day automatically, on GitHub's servers, whether your laptop is open or not.


What Is GitHub Actions?

GitHub Actions is GitHub's built-in automation system. You write a small configuration file that says "run this on a schedule," and GitHub takes care of the rest. It spins up a fresh computer, runs your script, and shuts down again. You pay nothing. It just works.

The configuration file is called a workflow and it lives in your repo at .github/workflows/sync.yml. We'll create it in this chapter.


Step 1: Push Your Code to GitHub

GitHub is where we store the code, so GitHub Actions can find and run it. Think of this step as uploading your project folder to the internet — but in a controlled, version-tracked way.

Install Git

Git is the tool that uploads your code to GitHub. Check if you already have it:

git --version
Enter fullscreen mode Exit fullscreen mode

If you see a version number, skip ahead. If not, download it from git-scm.com and install it with all the defaults.

Create the repo on GitHub

Go to github.com and log in. Click the + icon in the top right corner and select New repository.

Fill it in like this:

  • Repository name: youtube-to-spotify
  • Description: "Syncs a YouTube playlist to Spotify automatically."
  • Visibility: Public (so others can follow along from the article) or Private (if you'd rather keep it to yourself — both work fine with GitHub Actions)

Leave everything else as is and click Create repository.

GitHub will show you an empty repo page with some setup instructions. Leave that tab open — we'll need a URL from it in a moment.

Connect your local folder to GitHub

Back in your terminal, make sure you're inside your youtube-to-spotify project folder. Then run these commands one by one:

git init
Enter fullscreen mode Exit fullscreen mode

This turns your folder into a Git repository — it starts tracking changes.

git remote add origin https://github.com/YOUR_GITHUB_USERNAME/youtube-to-spotify.git
Enter fullscreen mode Exit fullscreen mode

Replace YOUR_GITHUB_USERNAME with your actual GitHub username. This tells Git where on the internet to send your code. The URL is also shown on that repo page GitHub gave you.

git add spotify.py youtube.py script.py requirements.txt
Enter fullscreen mode Exit fullscreen mode

This stages the four files — tells Git "these are the ones I want to upload." Notice .env is not in this list. We never add that one.

git commit -m "Initial commit"
Enter fullscreen mode Exit fullscreen mode

A commit is a saved snapshot of your code with a message describing what changed. This is your first one.

git push -u origin main
Enter fullscreen mode Exit fullscreen mode

This sends everything to GitHub. If it asks for your GitHub username and password, use your username and a Personal Access Token as the password — GitHub stopped accepting regular passwords for this. You can generate one at github.com/settings/tokens — click Generate new token (classic), give it a name, check the repo scope, and copy the token it shows you.

Once the push completes, refresh your GitHub repo page. Your four files should be there.

Your repo should now contain these files:

youtube-to-spotify/
├── .github/
│   └── workflows/
│       └── sync.yml        ← we'll create this
├── spotify.py
├── youtube.py
├── script.py
├── requirements.txt
└── .gitignore              ← we'll create this too
Enter fullscreen mode Exit fullscreen mode

Notice that .env is NOT in that list. It must never go to GitHub. We handle that next.


Step 2: Create a .gitignore File

A .gitignore file tells Git which files to ignore — to never upload, no matter what. Create a file called .gitignore in your project root with this content:

.env
venv/
__pycache__/
*.pyc
Enter fullscreen mode Exit fullscreen mode

This ensures your .env file — with all your private credentials — stays on your computer only. Your secrets never leave your machine.

Now commit and push it:

git add .gitignore
git commit -m "Add gitignore"
git push
Enter fullscreen mode Exit fullscreen mode

Step 3: Add Your Secrets to GitHub

Your script needs six credentials to run. Since the .env file isn't on GitHub, we store those values in GitHub Secrets — an encrypted store that GitHub Actions can read at runtime, but that nobody can see, not even you, after saving them.

Go to your repo on GitHub: github.com/Towernter/youtube-to-spotify

Click SettingsSecrets and variablesActionsNew repository secret.

Add each of these one by one:

Secret name Value
CLIENT_ID Your Spotify Client ID
CLIENT_SECRET Your Spotify Client Secret
REFRESH_TOKEN Your Spotify Refresh Token
SPOTIFY_PLAYLIST_ID Your Spotify playlist ID
API_KEY Your YouTube API key
YOUTUBE_PLAYLIST_ID PLGBuKfnErZlAkaUUy57-mR97f8SBgMNHh

The name must match exactly — capital letters, underscores. That's how the workflow file will reference them.


Step 4: Create the Workflow File

Inside your project, create the folder structure .github/workflows/ and inside it create a file called sync.yml.

Here is the complete workflow file:

name: Sync YouTube Playlist to Spotify

on:
  schedule:
    - cron: '0 0 * * *'   # runs every day at midnight UTC
  workflow_dispatch:        # also lets you trigger it manually from GitHub

jobs:
  sync:
    runs-on: ubuntu-latest

    steps:
      - name: Check out the code
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Run the sync script
        env:
          CLIENT_ID: ${{ secrets.CLIENT_ID }}
          CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }}
          REFRESH_TOKEN: ${{ secrets.REFRESH_TOKEN }}
          SPOTIFY_PLAYLIST_ID: ${{ secrets.SPOTIFY_PLAYLIST_ID }}
          API_KEY: ${{ secrets.API_KEY }}
          YOUTUBE_PLAYLIST_ID: ${{ secrets.YOUTUBE_PLAYLIST_ID }}
        run: python script.py
Enter fullscreen mode Exit fullscreen mode

Let's walk through what this does:

on: schedule — the cron expression 0 0 * * * means "at minute 0 of hour 0, every day." That's midnight UTC. You can adjust this to any time you like using crontab.guru — a free tool that translates cron expressions into plain English.

workflow_dispatch — this adds a "Run workflow" button on GitHub so you can trigger it manually anytime without waiting for the schedule. Very useful for testing.

runs-on: ubuntu-latest — GitHub spins up a fresh Ubuntu Linux machine for each run. It installs Python, installs your dependencies, runs the script, and disappears. Clean every time.

env block — this is where the secrets get injected. ${{ secrets.CLIENT_ID }} pulls the value you stored in GitHub Secrets and makes it available to the script as an environment variable, exactly the same way your .env file did on your local machine.

Now create the .github/workflows/ folder structure inside your project and save the file as sync.yml inside it. Then commit and push:

git add .github/workflows/sync.yml
git commit -m "Add GitHub Actions workflow"
git push
Enter fullscreen mode Exit fullscreen mode

GitHub will detect the workflow file automatically as soon as it's pushed.


Step 5: Trigger Your First Manual Run

Don't wait until midnight to see if it works. Let's test it now.

Go to your repo on GitHub and click the Actions tab. You'll see your workflow listed — "Sync YouTube Playlist to Spotify." Click on it, then click the Run workflow button on the right, then click the green Run workflow button in the dropdown.

GitHub queues the job. After a few seconds, a new run appears in the list with a yellow spinning circle. Click on it to watch it run live.

You'll see each step execute in order:

✅ Check out the code
✅ Set up Python
✅ Install dependencies
✅ Run the sync script
Enter fullscreen mode Exit fullscreen mode

Click on "Run the sync script" to expand it and see the actual output — the same output you saw when running locally in Chapter 5. If all four steps show green checkmarks, it worked.

Open Spotify. Your playlist is updated.


If the Workflow Fails

Red X on "Run the sync script"
Click the step to see the error output. The most common causes are a wrong secret name (check capitalisation) or a missing secret. Cross-reference the secret names in the workflow file against what you added in Step 3.

Red X on "Install dependencies"
Your requirements.txt might be missing or have a typo in a package name. Make sure it was committed and pushed to the repo.

The workflow doesn't appear in the Actions tab
The sync.yml file might be in the wrong location. It must be at exactly .github/workflows/sync.yml — two nested folders from the root of your repo.

The workflow runs but no songs are added
The script ran successfully but found nothing new to add — probably because you already ran it locally in Chapter 5 and the playlist is already up to date. That's not a failure, that's the script doing its job correctly.


What Happens Every Day From Here

At midnight UTC, GitHub wakes up, checks out your code, installs the dependencies, and runs script.py. The script fetches the YouTube playlist, finds any new songs on Spotify, adds them, removes ones that were taken off YouTube, reorders everything, and shuts down.

You do nothing. You just open Spotify and listen.

If the YouTube playlist owner adds a new song, it'll be in your Spotify playlist the next morning. If they remove one, it's gone from Spotify too. The two playlists stay in sync permanently.


The Complete Picture

Here's what you built across this series:

  • A Spotify developer app with the right permissions
  • A YouTube API key tied to your Google project
  • Three Python files that talk to both APIs and sync them intelligently
  • A .env file for local development and GitHub Secrets for production
  • A GitHub Actions workflow that runs the whole thing daily on a schedule

That is a real, deployed, automated software project. It has credentials management, API integration, error handling, scheduled execution, and version control. Those are not beginner concepts. You just learned them by building something you'll actually use.


Where to Go From Here

The repo at github.com/Towernter/youtube-to-spotify also contains script_advanced.py — the full version of the script with extra features: auto-updating the playlist description with artist names and genres, filling gaps with tracks from a specific artist, and managing multiple playlists at once. Once you're comfortable with the basics, that's worth exploring.

If you want to sync a different YouTube playlist, just update YOUTUBE_PLAYLIST_ID in your GitHub Secrets and the workflow will pick it up on the next run.

And if you found this series useful, share it. Someone else is out there with a YouTube playlist they wish was on Spotify.


🎵 Final Product

After following the steps in this tutorial, your playlist should look similar to the one below:

🎧 View the completed Spotify Playlist

Thanks for following along. Drop any questions in the comments — I read them all.

Top comments (0)