Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
e2c1f41
add variable file
codeblech Jul 10, 2024
7881b15
add lock file
codeblech Jul 10, 2024
94f8b6d
refactor main
codeblech Jul 10, 2024
80f2099
Update tf-apply.yaml
codeblech Jul 10, 2024
b806c0a
Update tf-apply.yaml
codeblech Jul 10, 2024
57a2aad
Update tf-apply.yaml
codeblech Jul 10, 2024
c1e7dff
Update tf-apply.yaml
codeblech Jul 10, 2024
ac3ba54
Update tf-apply.yaml
codeblech Jul 10, 2024
448561b
Update tf-apply.yaml
codeblech Jul 10, 2024
66743a6
Update tf-apply.yaml
codeblech Jul 10, 2024
cb77a0c
Update tf-apply.yaml
codeblech Jul 10, 2024
859a7ac
Update tf-apply.yaml
codeblech Jul 10, 2024
cce991f
Update tf-apply.yaml
codeblech Jul 10, 2024
b6eaa8b
Update tf-apply.yaml
codeblech Jul 10, 2024
a211300
Update tf-apply.yaml
codeblech Jul 10, 2024
1af23c2
Update tf-apply.yaml
codeblech Jul 10, 2024
5f31b68
Update tf-apply.yaml
codeblech Jul 10, 2024
d71519b
Update tf-apply.yaml
codeblech Jul 10, 2024
c5b5eff
Update tf-apply.yaml
codeblech Jul 10, 2024
0e28ce3
Update tf-apply.yaml
codeblech Jul 10, 2024
2410bd3
Update tf-apply.yaml
codeblech Jul 10, 2024
77a6268
Update tf-apply.yaml
codeblech Jul 10, 2024
d13a8bb
Update tf-apply.yaml
codeblech Jul 10, 2024
871fd74
Update tf-apply.yaml
codeblech Jul 10, 2024
78e1748
tryhard
codeblech Jul 10, 2024
e4a10c4
Update tf-apply.yaml
codeblech Jul 10, 2024
d7e5f6d
Update tf-apply.yaml
codeblech Jul 10, 2024
84a97fc
tryharder
codeblech Jul 10, 2024
49944a6
Update tf-apply.yaml
codeblech Jul 10, 2024
690bfe8
one more
codeblech Jul 10, 2024
8f9cf25
add TF_VAR suffix
codeblech Jul 10, 2024
6ec536a
Update tf-apply.yaml
codeblech Jul 10, 2024
58e3477
remove lock
codeblech Jul 10, 2024
0d4e52c
Update tf-apply.yaml
codeblech Jul 10, 2024
d5a8459
Update tf-apply.yaml
codeblech Jul 10, 2024
58bb386
Update tf-apply.yaml
codeblech Jul 11, 2024
28e9acd
Update tf-apply.yaml
codeblech Jul 11, 2024
a987cc2
Update tf-apply.yaml
codeblech Jul 11, 2024
f5cd071
Update tf-apply.yaml
codeblech Jul 11, 2024
8d7bc4b
Update tf-apply.yaml
codeblech Jul 11, 2024
c3ba60b
Update tf-apply.yaml
codeblech Jul 11, 2024
3e1f440
Update tf-apply.yaml
codeblech Jul 11, 2024
6471c70
Update tf-apply.yaml
codeblech Jul 11, 2024
c89ce5b
Added Song: A View to Kill
codeblech Jul 11, 2024
47f30d8
added .terraform.lock.hcl file
codeblech Jul 11, 2024
41d74f4
added tfstate file and its backup
codeblech Jul 11, 2024
9395422
Added song: Veridis Quo
codeblech Jul 11, 2024
19fe8f3
Remove song (ci/cd test)
dushyantpunk Jul 11, 2024
46c1c16
Merge pull request #1 from dushyantpunk/patch-1
codeblech Jul 11, 2024
496c08f
Update playlist link
codeblech Jul 11, 2024
4c782d5
kinda final
codeblech Jul 11, 2024
7c70762
add guide
codeblech Jul 11, 2024
edf2ab6
Update main.tf
codeblech Aug 10, 2024
bb30cf9
Update main.tf
codeblech Aug 13, 2024
7b256b3
add few tracks in main.tf
Jun 23, 2025
56db040
change main.tf
Jun 23, 2025
80a4711
Improve Puppeteer stability for slow login flow
Jun 23, 2025
b9d2973
Improve Puppeteer flow
Jun 23, 2025
9526e95
Improve Puppeteer flow-2
Jun 23, 2025
539e91c
Improve Puppeteer flow-3
Jun 23, 2025
1abb21d
Improve Puppeteer flow-4
Jun 23, 2025
98f08ab
Improve Puppeteer flow-4.1
Jun 23, 2025
d0ff7ef
new workflow logic
Jun 23, 2025
ca786b7
new workflow logic-1
Jun 23, 2025
de53bad
new workflow logic-2
Jun 23, 2025
3a9bbe6
new workflow logic-3
Jun 23, 2025
cee9d85
new workflow logic-4
Jun 23, 2025
93dc984
new workflow logic-5
Jun 23, 2025
8e0aa8a
change workflow
Jun 24, 2025
00fcb7e
change workflow-1
Jun 24, 2025
532ac60
change workflow-2
Jun 24, 2025
d422cba
change workflow-3
Jun 24, 2025
1cf2848
change workflow-4
Jun 24, 2025
4e0446d
change workflow-4
Jun 24, 2025
83b50ea
change all
Jun 24, 2025
7ad7fb4
all fix (maybe)
Jun 24, 2025
e6ffc89
all fix (maybe)-minor change
Jun 24, 2025
67abe2d
all fix (maybe)-minor change-1
Jun 24, 2025
b08bf29
all fix (maybe)-minor change-2
Jun 24, 2025
39b63e9
all fix (maybe)-minor change-3
Jun 24, 2025
db39513
all fix (maybe)-minor change-3.1
Jun 24, 2025
6a6547f
all fix (maybe)-minor change-3.2
Jun 24, 2025
ecb8319
all fix (maybe)-minor change-3.2
Jun 24, 2025
b1531d5
one more time
Jun 24, 2025
029e527
new one
Jun 24, 2025
b8250f3
terraform setup
Jun 24, 2025
9281e15
final-check
Jun 24, 2025
552ad4e
Update main.tf
Jun 25, 2025
85b05e5
Update tf-apply.yaml
Jun 25, 2025
e78618e
pass api dynamically
Jun 25, 2025
de50a96
hope this works
Jun 25, 2025
d9a0a8b
add song
gouravslnk Jul 4, 2025
1ca0e77
add starlight
gouravslnk Jul 4, 2025
8433669
add starlight
gouravslnk Jul 4, 2025
6f57181
what is your problem
gouravslnk Jul 4, 2025
d4d4384
remove current tfstate
gouravslnk Jul 4, 2025
190d716
add song
gouravslnk Jul 4, 2025
01c87bb
add Save Terraform State
gouravslnk Jul 4, 2025
0f1887f
add song
gouravslnk Jul 4, 2025
747fced
add song
gouravslnk Jul 4, 2025
887ed60
add tfstate again
gouravslnk Jul 4, 2025
0257bc7
add instructions to add our own playlist
gouravslnk Jul 4, 2025
de45bb8
update the workflow and made few changes
gouravslnk Jul 18, 2025
6fb8530
Update README.md
gouravslnk Jul 18, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
237 changes: 227 additions & 10 deletions .github/workflows/tf-apply.yaml
Original file line number Diff line number Diff line change
@@ -1,21 +1,238 @@
name: Update playlist
name: Update playlist with Spotify Auth

on:
push:
branches:
- main

jobs:
apply:
spotify-auth-and-apply:
runs-on: ubuntu-latest
name: Apply terraform
env:
TF_VAR_SPOTIFY_API_KEY: ${{ secrets.SPOTIFY_API_KEY }}
name: Authenticate and Apply
timeout-minutes: 15

steps:
- name: Checkout
uses: actions/checkout@v2
- name: Checkout repository
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.21'

- name: Install patched spotify_auth_proxy from fork
run: |
echo "$HOME/go/bin" >> $GITHUB_PATH
git clone -b fix/base-url-127 https://github.com/gouravslnk/terraform-provider-spotify
cd terraform-provider-spotify/spotify_auth_proxy
go build -o $HOME/go/bin/spotify_auth_proxy .
if ! command -v spotify_auth_proxy &> /dev/null; then
echo "::error::Installation failed"
exit 1
fi

- name: Run spotify_auth_proxy
env:
SPOTIFY_CLIENT_ID: ${{ secrets.SPOTIFY_CLIENT_ID }}
SPOTIFY_CLIENT_SECRET: ${{ secrets.SPOTIFY_CLIENT_SECRET }}
SPOTIFY_REDIRECT_URI: ${{ secrets.SPOTIFY_REDIRECT_URI }}
SPOTIFY_PROXY_BASE_URI: http://127.0.0.1:8080
run: |
spotify_auth_proxy --port 8080 > proxy.log 2>&1 &
echo "Waiting for auth URL..."
for i in {1..30}; do
if grep -q "Auth URL:" proxy.log; then break; fi
sleep 1
done
auth_url=$(grep "Auth URL:" proxy.log | awk '{print $3}')
api_key=$(grep "APIKey:" proxy.log | awk '{print $2}')
echo "AUTH_URL=$auth_url" >> $GITHUB_ENV
echo "SPOTIFY_API_KEY=$api_key" >> $GITHUB_ENV
if [ -z "$auth_url" ] || [ -z "$api_key" ]; then
echo "::error::Failed to get auth credentials"
cat proxy.log
exit 1
fi

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'

- name: Install Node dependencies
run: npm install [email protected] fs-extra@11

- name: Perform Spotify login and authorization
env:
AUTH_URL: ${{ env.AUTH_URL }}
SPOTIFY_USERNAME: ${{ secrets.SPOTIFY_USERNAME }}
SPOTIFY_PASSWORD: ${{ secrets.SPOTIFY_PASSWORD }}
run: |
node - <<'EOF'
const puppeteer = require('puppeteer');
const fs = require('fs-extra');
const delay = ms => new Promise(res => setTimeout(res, ms));
const randomDelay = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);
async function typeWithHumanDelay(page, selector, text) {
for (const char of text) {
await page.type(selector, char, { delay: randomDelay(30, 100) });
if (Math.random() > 0.8) await delay(randomDelay(50, 150));
}
}
async function clickByText(page, text, tag = '*') {
const elements = await page.$$(tag);
for (const el of elements) {
const content = await page.evaluate(el => el.textContent?.trim(), el);
if (content?.toLowerCase() === text.toLowerCase()) {
await el.click();
return true;
}
}
return false;
}
async function safeClick(page, selector, timeout = 10000) {
try {
await page.waitForSelector(selector, { visible: true, timeout });
await delay(500);
const element = await page.$(selector);
if (element) {
await element.click();
return true;
}
} catch {}
return false;
}

(async () => {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
defaultViewport: { width: 1280, height: 800 }
});
const page = await browser.newPage();
await page.setUserAgent('Mozilla/5.0');

try {
console.log("🌐 Navigating to Spotify Auth URL...");
await page.goto(process.env.AUTH_URL, { waitUntil: 'networkidle2', timeout: 60000 });
console.log("📍 Current page:", page.url());

if (page.url().includes('accounts.google.com')) {
throw new Error("❌ Redirected to Google login instead of Spotify login.");
}

console.log("📧 Entering email...");
await page.waitForSelector('input[type="email"], #login-username', { visible: true, timeout: 15000 });
await typeWithHumanDelay(page, 'input[type="email"], #login-username', process.env.SPOTIFY_USERNAME);
await delay(1000);

console.log("➡️ Clicking Continue...");
const continued = await clickByText(page, 'Continue') ||
await safeClick(page, 'button[data-testid="login-button"]') ||
await safeClick(page, 'button[type="submit"]');
if (!continued) throw new Error("❌ Continue button not found.");

await delay(3000);

const otpDetected = await page.evaluate(() =>
Array.from(document.querySelectorAll('*')).some(el =>
el.textContent?.toLowerCase().includes('6-digit code')
)
);

if (otpDetected) {
console.log("🔁 Switching to password login...");
const clicked = await clickByText(page, 'Log in with a password') ||
await safeClick(page, 'button[data-encore-id="buttonTertiary"]');
if (!clicked) throw new Error("❌ Could not find 'Log in with a password'.");
await delay(3000);
}

console.log("🔑 Entering password...");
await page.waitForSelector('input[type="password"]', { visible: true, timeout: 10000 });
await typeWithHumanDelay(page, 'input[type="password"]', process.env.SPOTIFY_PASSWORD);
await delay(1000);

console.log("🚀 Logging in...");
const loggedIn = await safeClick(page, '#login-button') ||
await safeClick(page, 'button[data-testid="login-button"]') ||
await safeClick(page, 'button[data-encore-id="buttonPrimary"]') ||
await clickByText(page, 'Log In');
if (!loggedIn) throw new Error("❌ Login button not found.");

await delay(5000);

const authorized = await safeClick(page, '#auth-accept') || await clickByText(page, 'Agree');
if (authorized) {
console.log("✅ Accepted authorization.");
await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 15000 });
}

const finalURL = page.url();
if (!finalURL.includes('callback?code=')) {
throw new Error(`❌ Authorization failed. Final URL: ${finalURL}`);
}

console.log("🎉 Spotify authorization successful!");
} catch (error) {
console.error("💥 Error during login:", error.message);
await page.screenshot({ path: 'spotify_error.png', fullPage: true });
await fs.writeFile('error_debug.html', await page.content());
process.exit(1);
} finally {
await browser.close();
}
})();
EOF

- name: Install jq
run: sudo apt-get update && sudo apt-get install -y jq

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.12.2

- name: Terraform Init
run: terraform init

- name: Clean Terraform State if Playlist Invalid
env:
SPOTIFY_API_KEY: ${{ env.SPOTIFY_API_KEY }}
run: |
if grep -q "spotify_playlist" terraform.tfstate; then
echo "Checking playlist ownership..."
PLAYLIST_ID=$(jq -r '.resources[] | select(.type=="spotify_playlist") | .instances[0].attributes.id' terraform.tfstate)
RESPONSE=$(curl -s -H "Authorization: Bearer $SPOTIFY_API_KEY" https://api.spotify.com/v1/playlists/$PLAYLIST_ID)
if echo "$RESPONSE" | grep -q "\"error\""; then
echo "❌ Playlist does not exist or does not belong to current user. Resetting state..."
rm -f terraform.tfstate terraform.tfstate.backup
else
echo "✅ Playlist exists and belongs to user. Continuing..."
fi
else
echo "ℹ️ No playlist in state. Continuing..."
fi

- name: Terraform Validate
run: terraform validate

- name: Terraform Plan
env:
SPOTIFY_API_KEY: ${{ env.SPOTIFY_API_KEY }}
run: terraform plan -var "SPOTIFY_API_KEY=${SPOTIFY_API_KEY}"

- name: Terraform Apply
env:
SPOTIFY_API_KEY: ${{ env.SPOTIFY_API_KEY }}
run: terraform apply -auto-approve -var "SPOTIFY_API_KEY=${SPOTIFY_API_KEY}"

- name: terraform apply
uses: dflook/terraform-apply@v1
- name: Upload debug artifacts
if: failure()
uses: actions/upload-artifact@v4
with:
auto_approve: true
name: spotify-debug
path: |
spotify_error.png
error_debug.html
proxy.log
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ crash.log
crash.*.log

# Exclude all .tfvars files, which are likely to contain sensitive data, such as
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# password, private keys, and other secrets. These should not be part of version
# control as they are data points which are potentially sensitive and subject
# to change depending on the environment.
*.tfvars
*.tfvars.json
Expand Down
23 changes: 23 additions & 0 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading