Skip to main content
tutorial

Unity Build Automation Part 2: Deploy Everywhere - FTP, Cloud & Notifications

Angry Shark Studio
14 min read
Unity Python Build Automation FTP Google Drive WebGL Deployment CI/CD Tutorial DevOps

Your Unity build finished at 2 AM. Perfect timing. Now what?

Manually upload 500MB to FTP? Zip and send via email? Copy to Google Drive? Wake up at 2 AM to do it?

In Part 1, we automated Unity builds with Python. Builds run automatically, save hours of clicking, and handle all platforms.

But builds sitting on your local machine help nobody. QA can’t test them. Clients can’t see them. Your web server doesn’t magically update itself.

Part 2 solves deployment. Build finishes, files upload to FTP automatically, Google Drive link gets generated, team receives email notification. All automatic. Zero manual intervention.

Technical diagram showing Unity build automation deployment flow: Unity cube connects to Python script, which deploys to FTP server, cloud storage, and email notifications

What You’ll Learn

This tutorial shows you how to:

  • Deploy WebGL builds directly to your web server via FTP/FTPS
  • Upload Windows and Mac builds to Google Drive with shareable links
  • Send email notifications when builds complete (or fail)
  • Secure all credentials with environment variables (never commit passwords)
  • Handle large files, network interruptions, and common deployment errors
  • Integrate deployment into your existing Part 1 automation

Prerequisites Check

You need Part 1 working first. If you haven’t completed it, start there: Unity Build Automation Part 1.

System Requirements:

  • Python 3.8+ installed
  • Unity 2021.3 LTS or newer
  • Part 1 setup complete and tested

New Python Packages:

pip install python-dotenv
pip install google-api-python-client google-auth-httplib2

Clone or Update the Repository:

git clone https://github.com/angrysharkstudio/Unity-Python-Build-Automation.git
cd Unity-Python-Build-Automation

# Or if you already cloned it for Part 1:
git pull origin main

The repository now includes deployment features in BuildAutomation/build_cli.py with --upload and --gdrive-upload flags.

Setting Up Secure Environment Variables

Never hardcode credentials in Python scripts. Ever.

One accidental Git commit exposes your FTP password to the world. GitHub automatically scans for credentials and flags repositories. Hosting providers lock accounts when credentials leak.

Environment variables solve this. Credentials live in a .env file that never gets committed. Each developer has their own .env. Production servers have separate credentials. No secrets in code.

Create Your Environment File:

# Navigate to your Unity project root
cd Unity-Python-Build-Automation

# Copy the example
cp BuildAutomation/.env.example .env

# Add .env to gitignore (if not already there)
echo ".env" >> .gitignore

Basic .env Structure:

Open .env in your text editor and configure the services you need:

# Unity Settings
UNITY_PATH="/Applications/Unity/Hub/Editor/2022.3.15f1/Unity.app/Contents/MacOS/Unity"
UNITY_PROJECT_PATH="/path/to/your/UnityProject"

# FTP Settings (for WebGL deployment)
WEBGL_FTP_ENABLED=true
WEBGL_FTP_HOST=ftp.yourserver.com
WEBGL_FTP_USERNAME=your_username
WEBGL_FTP_PASSWORD=your_secure_password
WEBGL_FTP_REMOTE_PATH=/public_html/games/yourgame
WEBGL_FTP_OVERWRITE=true

# Google Drive Settings (for Windows/Mac builds)
WINDOWS_GDRIVE_ENABLED=true
GDRIVE_CREDENTIALS_FILE=BuildAutomation/credentials.json
GDRIVE_FOLDER_ID=1a2b3c4d5e6f7g8h9i0j

# Email Notifications (optional)
EMAIL_ENABLED=true
EMAIL_SMTP_HOST=smtp.gmail.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USERNAME=your-email@gmail.com
EMAIL_SMTP_PASSWORD=your-app-password
EMAIL_FROM=your-email@gmail.com
EMAIL_TO=team@company.com,qa@company.com

Loading Environment Variables in Python:

The repository’s build_cli.py uses python-dotenv to load these values:

from dotenv import load_dotenv
import os

# Load .env file
load_dotenv()

# Access variables safely
ftp_host = os.getenv('WEBGL_FTP_HOST')
if not ftp_host:
    print("Warning: FTP not configured (WEBGL_FTP_HOST not set)")

# Check if feature is enabled
ftp_enabled = os.getenv('WEBGL_FTP_ENABLED', 'false').lower() == 'true'

This pattern means features are opt-in. No FTP credentials? No problem. Deployment gets skipped. No crashes, no errors.

WebGL FTP Deployment

WebGL builds need web servers. Uploading 100MB+ of files manually after every build wastes time. FTP automates this completely.

Why FTP for WebGL:

  1. Direct server deployment - Files go straight to production
  2. Instant testing - Test on real domain with real URLs
  3. No manual transfers - Zero FileZilla sessions
  4. Automatic overwrites - Old builds get replaced automatically

How It Works:

When you build WebGL with the --upload flag:

python build_cli.py webgl --upload

The script:

  1. Builds your Unity WebGL project
  2. Connects to your FTP server
  3. Uploads all files preserving directory structure
  4. Reports success or failure

Actual Command from Repository:

# WebGL build with automatic FTP upload
python BuildAutomation/build_cli.py webgl --upload

# Build multiple platforms with selective deployment
python BuildAutomation/build_cli.py webgl windows --upload

FTP Connection Security:

The repository supports both FTP and FTPS (FTP over TLS). Always use FTPS when your server supports it.

Check your .env configuration:

WEBGL_FTP_HOST=ftp.yourserver.com  # Use ftps:// prefix for explicit FTPS
WEBGL_FTP_USERNAME=your_username
WEBGL_FTP_PASSWORD=your_secure_password

Common FTP Configuration Examples:

# Shared hosting (usually plain FTP, unfortunately)
WEBGL_FTP_HOST=ftp.yourdomain.com
WEBGL_FTP_REMOTE_PATH=/public_html/games/yourgame

# VPS or dedicated server (often supports FTPS)
WEBGL_FTP_HOST=ftps://your-server-ip
WEBGL_FTP_REMOTE_PATH=/var/www/html/games/yourgame

# Subdomain deployment
WEBGL_FTP_HOST=ftp.yourdomain.com
WEBGL_FTP_REMOTE_PATH=/game.yourdomain.com/public_html

Overwrite Protection:

Set WEBGL_FTP_OVERWRITE=false to prevent accidentally overwriting production builds. The script will fail instead of overwriting, giving you a chance to verify.

Testing Your FTP Setup:

Before automating, test your FTP credentials manually with FileZilla or another FTP client. Verify:

  • You can connect
  • You have write permissions to the remote path
  • Directory structure matches your expectations

Once manual FTP works, automation will work.

Google Drive Integration

Large Windows or Mac builds need distribution. Google Drive provides:

  • Shareable links for QA and stakeholders
  • Automatic version history
  • Large file support (up to 5TB)
  • No hosting costs

Google Drive Service Account Setup:

Service accounts give your scripts limited, controlled access to Google Drive without requiring manual authorization every time.

Step 1: Create Google Cloud Project

  1. Go to Google Cloud Console
  2. Create new project (or use existing)
  3. Name it something like “Unity Build Automation”

Step 2: Enable Drive API

  1. Navigate to “APIs & Services” > “Library”
  2. Search for “Google Drive API”
  3. Click “Enable”

Step 3: Create Service Account

  1. Go to “APIs & Services” > “Credentials”
  2. Click “Create Credentials” > “Service Account”
  3. Name it “unity-build-uploader”
  4. Click “Create and Continue”
  5. Skip optional role assignment
  6. Click “Done”

Step 4: Generate JSON Key

  1. Click on your new service account
  2. Go to “Keys” tab
  3. Click “Add Key” > “Create New Key”
  4. Choose “JSON”
  5. Save the file to BuildAutomation/credentials.json

Step 5: Share Drive Folder

  1. Create a folder in Google Drive for builds
  2. Get the folder ID from the URL (it’s the long string after /folders/)
  3. Share the folder with your service account email (looks like unity-build-uploader@project-name.iam.gserviceaccount.com)
  4. Give it “Editor” permissions

Configure in .env:

WINDOWS_GDRIVE_ENABLED=true
GDRIVE_CREDENTIALS_FILE=BuildAutomation/credentials.json
GDRIVE_FOLDER_ID=1a2b3c4d5e6f7g8h9i0j

Using Google Drive Upload:

# Windows build with Google Drive upload
python BuildAutomation/build_cli.py windows --gdrive-upload

# Mac build with Google Drive upload
python BuildAutomation/build_cli.py mac --gdrive-upload

# Build both and upload to Drive
python BuildAutomation/build_cli.py windows mac --gdrive-upload

The script automatically:

  • Compresses the build folder into a ZIP
  • Uploads to your specified Google Drive folder
  • Generates a shareable link
  • Prints the link in the console
  • Optionally emails the link to your team

File Naming:

Uploaded files are named with timestamps:

Build_Windows_20250923_143022.zip
Build_Mac_20250923_143155.zip

This automatic versioning means you never accidentally overwrite builds. Every build is preserved in Google Drive with clear timestamps.

Email Notifications

Builds finish at weird hours. Deployments succeed or fail. Your team needs to know.

Email notifications keep everyone informed without manual updates.

SMTP Configuration:

EMAIL_ENABLED=true
EMAIL_SMTP_HOST=smtp.gmail.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USERNAME=your-email@gmail.com
EMAIL_SMTP_PASSWORD=your-app-password
EMAIL_FROM=your-email@gmail.com
EMAIL_TO=team@company.com,qa@company.com

Gmail App Password Setup:

Gmail requires App Passwords for SMTP. Your regular password won’t work.

  1. Enable 2-Factor Authentication on your Google account
  2. Go to App Passwords page
  3. Select “Mail” and “Other (Custom name)”
  4. Name it “Unity Build Automation”
  5. Copy the generated password
  6. Use this password in EMAIL_SMTP_PASSWORD

What Gets Sent:

When builds complete, your team receives emails with:

  • Platform name (Windows, WebGL, etc.)
  • Build status (Success or Failed)
  • Build duration
  • Output file size
  • Download links (for Google Drive uploads)
  • Error messages (if build or deployment failed)

Sample Email Content:

Subject: Unity Build Complete: Windows

Build Report:

Platform: Windows
Status: Success
Duration: 3.2 minutes
Output Size: 487 MB

Google Drive Link:
https://drive.google.com/file/d/1AbCdEfGhIjK/view

Build completed at: 2025-09-23 14:30:22

Failure Notifications:

If builds or deployments fail, emails include error details:

Subject: Unity Build FAILED: WebGL

Build Report:

Platform: WebGL
Status: Failed
Error: FTP connection refused (check credentials)

Build failed at: 2025-09-23 14:35:10

This immediate feedback means you know about problems without checking logs manually.

Complete Deployment Pipeline

Bringing everything together for real-world workflows.

Example 1: WebGL to Production Server

# Build and deploy WebGL directly to your web server
python BuildAutomation/build_cli.py webgl --upload

This command:

  1. Builds WebGL in Unity
  2. Compresses files (if configured)
  3. Uploads to FTP server
  4. Sends email confirmation
  5. Prints deployment URL

Example 2: Windows Build for QA

# Build Windows, upload to Drive, notify team
python BuildAutomation/build_cli.py windows --gdrive-upload

This command:

  1. Builds Windows standalone
  2. Compresses to ZIP
  3. Uploads to Google Drive
  4. Emails shareable link to team
  5. Prints Drive link in console

Example 3: Full Multi-Platform Release

# Build everything, deploy where appropriate
python BuildAutomation/build_cli.py webgl windows mac --upload --gdrive-upload

This command:

  1. Builds WebGL, Windows, and Mac
  2. Uploads WebGL to FTP
  3. Uploads Windows and Mac to Google Drive
  4. Sends consolidated email with all links
  5. Completes entire release process

Handling Errors Gracefully:

Each deployment method includes error handling:

# Pseudo-code from repository
try:
    if ftp_enabled and platform == "webgl":
        upload_to_ftp(build_path, ftp_config)
        print("FTP upload successful")
except FTPError as e:
    print(f"FTP upload failed: {e}")
    send_error_notification(f"WebGL deployment failed: {e}")
    # Continue with other platforms

One failure doesn’t stop everything. If FTP fails, Google Drive still uploads. If email fails, builds still complete. Resilient automation that doesn’t break your entire workflow.

Advanced Pipeline Example:

# Complete automated workflow
python BuildAutomation/build_cli.py \
    webgl --upload \
    windows --gdrive-upload \
    mac --gdrive-upload

This single command:

  • Builds 3 platforms
  • Deploys WebGL to production
  • Uploads Windows to Drive
  • Uploads Mac to Drive
  • Emails team with all 3 links
  • Takes ~15 minutes total

Compare to manual process:

  • Build WebGL: 5 minutes + 10 minutes manual FTP upload
  • Build Windows: 5 minutes + 5 minutes manual Drive upload
  • Build Mac: 8 minutes + 5 minutes manual Drive upload
  • Total: ~40 minutes of manual work

Automation: 15 minutes, zero manual steps.

Troubleshooting Common Issues

FTP Connection Refused

Error: [Errno 111] Connection refused

Solutions:

  • Verify FTP_HOST is correct (no http:// prefix)
  • Check if server uses non-standard port
  • Test connection with FileZilla first
  • Verify firewall allows FTP (port 21)
  • Try FTPS if your server supports it

FTP Permission Denied

Error: 550 Permission denied

Solutions:

  • Verify FTP user has write permissions
  • Check remote path exists
  • Ensure remote path syntax is correct
  • Try connecting with FileZilla using same credentials

Google Drive Authentication Failed

Error: Invalid service account credentials

Solutions:

  • Verify credentials.json path is correct
  • Check service account has Drive API enabled
  • Confirm Drive folder is shared with service account email
  • Download fresh JSON key if corrupted

Google Drive Quota Exceeded

Error: User rate limit exceeded

Solutions:

  • Google has upload quotas (750GB/day for free accounts)
  • Wait 24 hours and try again
  • Delete old builds from Drive to free space
  • Upgrade to Google Workspace for higher limits

Email Not Sending (Gmail)

Error: Username and Password not accepted

Solutions:

  • Use App Password, not regular password
  • Enable 2-Factor Authentication first
  • Check SMTP port is 587 (not 465 or 25)
  • Verify EMAIL_SMTP_HOST is smtp.gmail.com
  • Some regions may block Gmail SMTP

Email Timeout

Error: timed out

Solutions:

  • Check internet connection
  • Verify firewall allows port 587
  • Try different SMTP server
  • Increase timeout in script (if you modify it)

Build Succeeds but Deployment Fails

Check .env file:

# Make sure feature is enabled
WEBGL_FTP_ENABLED=true  # Must be exactly 'true'
EMAIL_ENABLED=true

# Common mistake:
WEBGL_FTP_ENABLED=True  # Wrong capitalization

Common Pitfalls and Solutions

Pitfall 1: Hardcoding Credentials

# WRONG - Never do this
ftp_password = "mypassword123"
drive_folder = "1a2b3c4d5e6f7g"

# RIGHT - Always use environment variables
ftp_password = os.getenv('WEBGL_FTP_PASSWORD')
if not ftp_password:
    raise ValueError("WEBGL_FTP_PASSWORD not set in .env")

Pitfall 2: Committing .env to Git

# Check your .gitignore includes:
.env
credentials.json
*.pyc
__pycache__/

If you accidentally committed .env:

# Remove from Git but keep local file
git rm --cached .env
git commit -m "Remove .env from repository"
git push

# Change all passwords immediately

Pitfall 3: No Error Handling for Network Issues

# WRONG - Will crash on network error
upload_to_ftp(build_path)

# RIGHT - Graceful error handling
try:
    upload_to_ftp(build_path)
    print("Upload successful")
except Exception as e:
    print(f"Upload failed: {e}")
    send_error_notification(e)
    # Continue with other deployments

Pitfall 4: Uploading Uncompressed Builds

Windows builds can be 500MB+ uncompressed. Always compress:

# Repository automatically compresses for Google Drive
python build_cli.py windows --gdrive-upload
# Creates Build_Windows_20250923.zip automatically

For FTP, consider compressing WebGL builds to save bandwidth and upload time.

Pitfall 5: Same Credentials for All Environments

# WRONG - Using production credentials everywhere
WEBGL_FTP_HOST=ftp.production-server.com

# RIGHT - Use different .env for dev/staging/production
# .env.dev
WEBGL_FTP_HOST=ftp.dev-server.com

# .env.production
WEBGL_FTP_HOST=ftp.production-server.com

Load environment-specific configs:

# Development
python build_cli.py webgl --upload

# Production (use separate .env file)
cp .env.production .env
python build_cli.py webgl --upload

Quick Reference

Essential Commands:

# Install dependencies
pip install python-dotenv google-api-python-client

# Setup environment
cp BuildAutomation/.env.example .env
# Edit .env with your credentials

# WebGL with FTP deployment
python BuildAutomation/build_cli.py webgl --upload

# Windows with Google Drive
python BuildAutomation/build_cli.py windows --gdrive-upload

# Multiple platforms with deployment
python BuildAutomation/build_cli.py webgl windows --upload --gdrive-upload

Environment Variables Checklist:

# FTP (for WebGL deployment)
WEBGL_FTP_ENABLED=true
WEBGL_FTP_HOST=
WEBGL_FTP_USERNAME=
WEBGL_FTP_PASSWORD=
WEBGL_FTP_REMOTE_PATH=

# Google Drive (for Windows/Mac deployment)
WINDOWS_GDRIVE_ENABLED=true
GDRIVE_CREDENTIALS_FILE=BuildAutomation/credentials.json
GDRIVE_FOLDER_ID=

# Email (optional notifications)
EMAIL_ENABLED=true
EMAIL_SMTP_HOST=smtp.gmail.com
EMAIL_SMTP_PORT=587
EMAIL_SMTP_USERNAME=
EMAIL_SMTP_PASSWORD=
EMAIL_FROM=
EMAIL_TO=

Service Account Setup:

  1. Create Google Cloud project
  2. Enable Google Drive API
  3. Create service account
  4. Download JSON credentials
  5. Share Drive folder with service account email

Gmail App Password:

  1. Enable 2-Factor Authentication
  2. Visit https://myaccount.google.com/apppasswords
  3. Generate password for “Unity Build Automation”
  4. Use generated password in .env

Best Practices

Security Best Practices:

  1. Never commit credentials - Always use .env files
  2. Rotate passwords regularly - Change FTP/email passwords every 3-6 months
  3. Use FTPS when possible - Encrypt FTP connections
  4. Limit service account permissions - Only grant Drive access needed
  5. Use separate credentials per project - Don’t reuse passwords
  6. Enable 2FA everywhere - Gmail, Google Cloud, FTP servers
  7. Log sensitive operations - Track who deployed what and when

Performance Best Practices:

  1. Compress before uploading - Repository does this automatically for Drive
  2. Use chunked uploads - Repository handles this for large files
  3. Implement retry logic - Repository includes automatic retries
  4. Add upload timeouts - Prevent hanging on slow connections
  5. Clean up old builds - Delete builds older than 30 days from Drive
  6. Monitor upload bandwidth - Avoid deploying during peak hours

Organization Best Practices:

  1. Version your deployments - Repository uses timestamps automatically
  2. Keep deployment logs - Save console output for troubleshooting
  3. Document your setup - README in your project explaining configuration
  4. Archive old builds - Move to separate Drive folder after 30 days
  5. Tag releases - Use Git tags when deploying to production
  6. Maintain separate environments - Dev, staging, production configurations

Workflow Best Practices:

  1. Test locally first - Build without deployment flags to verify builds work
  2. Deploy to staging - Test deployment to staging server before production
  3. Notify team - Always enable email notifications for production deployments
  4. Schedule large uploads - Deploy big builds overnight to avoid bandwidth issues
  5. Backup before deploy - Keep previous build accessible before overwriting
  6. Verify after deploy - Check FTP server or Drive link after upload completes

Conclusion

You’ve automated the complete build-to-deployment pipeline. Builds finish, files upload automatically, team gets notified. No manual FTP sessions, no forgetting to send links, no 2 AM wake-ups.

What We Built:

  • Secure environment configuration with .env files
  • Automatic WebGL deployment to FTP servers
  • Google Drive uploads for Windows and Mac builds
  • Email notifications for build and deployment status
  • Error handling that doesn’t break your entire workflow
  • Production-ready automation used in real studios

The Complete Workflow:

# Single command for full deployment
python BuildAutomation/build_cli.py webgl windows mac --upload --gdrive-upload

This command now handles:

  • Building all three platforms
  • Deploying WebGL to your web server
  • Uploading Windows and Mac to Google Drive
  • Emailing shareable links to your team
  • All in under 20 minutes with zero manual intervention

Repository and Code:

Everything shown in this tutorial exists in the repository:

Next Steps:

Part 3 will cover:

  • Pre-build hooks for automation
  • Build reliability and error recovery
  • Advanced multi-project setups
  • Custom deployment strategies
  • Personal developer workflows

Until then, automate your deployments and get back to building games instead of uploading builds.

Questions about deployment? Found a bug? Open an issue on GitHub or reach out through our contact page.

Angry Shark Studio Logo

About Angry Shark Studio

Angry Shark Studio is a professional Unity AR/VR development studio specializing in mobile multiplatform applications and AI solutions. Our team includes Unity Certified Expert Programmers with extensive experience in AR/VR development.

Related Articles

More Articles

Explore more insights on Unity AR/VR development, mobile apps, and emerging technologies.

View All Articles

Need Help?

Have questions about this article or need assistance with your project?

Get in Touch