self-hosted CI runner-এর একটি অস্বস্তিকর স্বভাব আছে: তারা সবকিছু মনে রাখে। ক্যাশ, টোকেন, গত বসন্তে কেউ "সাময়িকভাবে" যোগ করা একটি ডিপ্লয় কী। নিজের ব্রাঞ্চের জন্য এতে সমস্যা নেই। সমস্যা শুরু হয় যখন এমন কারও কাছ থেকে pull request আসে যার নাম আপনি কখনো শোনেননি — অথবা আপনার নিজের AI এজেন্টের কাছ থেকে, যে এমন প্যাচ লিখেছে যা এখনো কেউ পড়েনি।
পরিচ্ছন্ন উত্তর হলো প্রতি রানে একটি মেশিন। ক্লোন করুন, ইনস্টল করুন, টেস্ট করুন, মেশিনটি ফেলে দিন।
একটি রান দেখতে কেমন
স্যান্ডবক্স হলো একটি Firecracker microVM, যা প্রায় এক সেকেন্ডে Python 3.12, Node.js 22, git ও curl নিয়ে চালু হয়। বাইরে যাওয়ার ইন্টারনেট কাজ করে, তাই git clone আর pip install -r requirements.txt স্বাভাবিকভাবেই চলে। ভেতরে আসার কোনো পোর্ট নেই — চলার সময় কেউ টেস্ট পরিবেশে সংযোগ করতে পারে না।
CI জবের দিক থেকে পুরো কাজটি একটি ছোট স্ক্রিপ্ট। এখানে Python SDK দিয়ে লেখা সংস্করণ, যা যেকোনো CI জব থেকে ডাকা যায়:
import os, sys
from eqvps import Sandbox
repo, ref = os.environ["REPO_URL"], os.environ["PR_SHA"]
with Sandbox.create(tariff="standard", ttl=1800) as sb:
sb.exec(f"git clone {repo} /root/app && cd /root/app && git checkout {ref}", timeout=55)
sb.exec("cd /root/app && pip install -r requirements.txt", timeout=55)
task = sb.exec("cd /root/app && python3 -m pytest -q", background=True)
result = task.wait(on_output=lambda out, err: print(out, end=""))
sys.exit(result.exit_code or 0)
টোকেনটি আপনার CI সিক্রেটে EQVPS_API_KEY নামে থাকে। আপনার CI-এর আর কিছু — না ডিপ্লয় কী, না ক্লাউড ক্রেডেনশিয়াল — স্যান্ডবক্সে যায় না। with ব্লক শেষ হলে স্যান্ডবক্স মুছে ফেলা হয়, জব মাঝপথে ক্র্যাশ করলেও।
টেস্ট রানটি নিজেই একটি ব্যাকগ্রাউন্ড টাস্ক, কারণ একটি সিঙ্ক্রোনাস কমান্ড 55 সেকেন্ডে থেমে যায়। ব্যাকগ্রাউন্ড টাস্ক চলার সময় আউটপুট পাঠাতে থাকে এবং স্যান্ডবক্সের TTL পর্যন্ত চলতে পারে — এখানে এটি 30 মিনিট রাখা হয়েছে, যাতে আটকে যাওয়া টেস্ট বিল বাড়াতে না পারে।
যে সীমাগুলোর মুখোমুখি আপনি সত্যিই হবেন
এগুলো নিয়ে খোলাখুলি বললে আপনার একটা পুরো বিকেল বাঁচে।
একসঙ্গে চালানো। একটি অ্যাকাউন্টে 20টি স্যান্ডবক্স থাকতে পারে, কিন্তু একই সময়ে মাত্র 2টি কমান্ড চলে। CI-এর জন্য এর মানে দুটি জব সত্যিকারের সমান্তরালে। একসঙ্গে আসা দশটি PR সারিতে দাঁড়াবে। আপনার পাইপলাইন যদি টেস্টগুলো 16টি worker-এ ভাগ করে, তবে মূল পাইপলাইনের জন্য এটি সঠিক টুল নয় — সেটি VPS-এ নিজের runner-এ রাখুন, আর অবিশ্বস্ত লেনের জন্য স্যান্ডবক্স ব্যবহার করুন।
ভেতরে কনটেইনার নেই। স্যান্ডবক্সের সঙ্গে Docker আসে না। যে ইউনিট ও ইন্টিগ্রেশন টেস্টে Postgres কনটেইনার লাগে, সেগুলো যেমন আছে তেমন চলবে না; SQLite বা মেমরির নকল অবজেক্টের বিরুদ্ধে চলা টেস্ট চলবে।
ফাইল। API দিয়ে আপলোড ও ডাউনলোড প্রতি ফাইলে সর্বোচ্চ 5 MB। আর্কাইভ আপলোড না করে স্যান্ডবক্সের ভেতরে git দিয়ে কোড আনুন।
খরচ কত
আপনি ট্যারিফের vCPU ও RAM-এর জন্য প্রতি সেকেন্ডে পরিশোধ করেন, ন্যূনতম 60 সেকেন্ড, প্রিপেইড ব্যালান্স থেকে — কোনো সাবস্ক্রিপশন ছাড়া।
| রান | ট্যারিফ | আনুমানিক খরচ |
|---|---|---|
| লিন্ট + ইউনিট টেস্ট, 1 মিনিট | small (0.5 vCPU, 1 GB) | $0.0006 |
| পূর্ণ স্যুট, 3 মিনিট | standard (1 vCPU, 2 GB) | $0.0033 |
| বিল্ড + টেস্ট, 10 মিনিট | plus (2 vCPU, 4 GB) | $0.022 |
এই দামে আসল প্রশ্ন খরচ নয়, বরং আপনার নির্ধারিত সময়ের মধ্যে টেস্ট শেষ হয় কি না। আপনার সবচেয়ে ধীর সফল রানের চেয়ে TTL একটু বেশি রাখুন।
যুক্তিসঙ্গত ভাগাভাগি
আমাদের পরামর্শ: বিশ্বস্ত ব্রাঞ্চগুলো আপনার দ্রুত, ক্যাশযুক্ত runner-এ রাখুন। যা কিছু আপনি লেখেননি — fork, বাইরের অবদানকারী, এজেন্টের তৈরি প্যাচ — সেগুলো আগে স্যান্ডবক্সের মধ্য দিয়ে পাঠান। স্যান্ডবক্সের রান সফল হলে এবং কোনো মানুষ diff দেখে নিলে, সেটি বিশ্বস্ত পাইপলাইনে তুলে দিন।
এভাবে আপনার একটি লেন থাকে যেখানে গতি ও ক্যাশ গুরুত্বপূর্ণ, আর আরেকটি যেখানে পরিষ্কার মেশিন গুরুত্বপূর্ণ — কোনো একটি টুলকে দুটোই হতে বাধ্য না করে।
স্যান্ডবক্সের পরিচিতি আর সংযোগ নির্দেশিকা দিয়ে শুরু করুন — নতুন অ্যাকাউন্ট $1-এর স্যান্ডবক্স সময় পায়, যা কয়েকশো ছোট টেস্ট রানের জন্য যথেষ্ট। ওপরে ব্যবহৃত প্রতিটি মেথড আছে SDK রেফারেন্সে, আর সঠিক বিলিং নিয়ম আছে স্যান্ডবক্সের সীমা ও বিলিং-এ।
সম্পর্কিত: কোড রিভিউ ও PR যাচাইয়ের জন্য স্যান্ডবক্স এবং AI এজেন্টের জন্য স্যান্ডবক্স।
মন্তব্য
এখনো কোনো মন্তব্য নেই। প্রথম হোন।