RE:NODE

Pre-flight check: დაწყვეტილი GitHub deploy-ის დაჭერა გაშვებამდე

ავტორი RE:NODE-ის გუნდი
16 წუთის საკითხავი


უმეტესი deploy, რომელიც ვარდება, თვითონ deploy-ზე არ ვარდება. კოდი ჩამოიტვირთა, დამოკიდებულებები დაინსტალირდა, კონტეინერი ჩაირთო და მერე აპლიკაცია გამოდის, რადგან start სკრიპტი არ არის, ან ის უსმენს 3000 პორტს, სადაც გარედან ვერავინ აღწევს, ან ეძებს .next საქაღალდეს, რომელიც არავის აუშენებია. ეს შეცდომები რეპოზიტორიაშივე ჩანს, სანამ ერთი ბაიტიც გაიგზავნება. პანელის GitHub ჩანართზე pre-flight check კითხულობს რეპოზიტორიას, ადარებს იმას, როგორ ჩართავს სერვერი რეალურად, და ჩამოთვლის რა გაფუჭდება, ყველაზე სერიოზულიდან დაწყებული, გასწორების ვარიანტით, რომლის დაკოპირებაც შეგიძლია.

ამ პოსტში წერია, რას კითხულობს check, როგორ იკითხება ბარათი, რა სახის პრობლემას პოულობს (თითოეულისთვის რეალური კონფიგურაციის მაგალითით) და როგორ უნდა გაასწორო. ასევე წერია, რას ვერ ხედავს, რადგან მწვანე ბარათი იმის გარანტია არ არის, რომ აპლიკაცია იმუშავებს. უმეტესი გასწორება ნებისმიერ ჰოსტზე მუშაობს: ჩაწერილი პორტი ან localhost-ზე მიბმა deploy-ს ყველგან ანგრევს და არა მხოლოდ RE:NODE-ზე.

რას კითხულობს check და რას არასდროს ეხება#

check ორი რამით მუშაობს: ბრენჩის ერთი რეკურსიული ხის სია და სახელით ჩამოტვირთული რამდენიმე პატარა ფაილი. ხის სია მხოლოდ გზებია და ზომები, შიგთავსის გარეშე. ფაილები, რომლებსაც შეიძლება კითხულობდეს, ისინია, რომლებიც განსაზღვრავენ აპლიკაციის ჩართვას: package.json, deno.json ან deno.jsonc, go.mod და მთავარი პაკეტის Go ფაილები, requirements.txt ან pyproject.toml, .nvmrc, .env.example და შესვლის ფაილი, რომელსაც სერვერი გაუშვებდა. რეპოზიტორიას არასდროს კლონავს და ყველა 256 KB-ზე დიდ ფაილს ტოვებს, რადგან ჩატვირთვისას შესამოწმებელი არაფერია ასეთ დიდ ფაილში.

ის ორ ადგილას მუშაობს. როცა GitHub ჩანართზე რეპოზიტორიას და ბრენჩს ირჩევ, ბმის შენახვამდე ეშვება, ამიტომ პრობლემებს გაშვებამდე ხედავ. ამის შემდეგ ჩანართზე ყოველ შესვლაზე ხელახლა ეშვება. შედეგები commit-ის მიხედვით ათი წუთით ინახება, მაგრამ ბრენჩის head-ს ყოველ ჯერზე ეკითხება, ამიტომ ახლახან გაკეთებული push მაშინვე შეინიშნება და cache მხოლოდ იმას ზოგავს, რომ უცვლელი ფაილები ხელახლა არ იკითხოს.

სამი რამ განზრახ არ კეთდება:

  • `.env`-ს არასდროს ხსნის. commit-ში მოხვედრილი .env მხოლოდ ფაილის სახელით ფიქსირდება. მისი შიგთავსი არ იტვირთება, ამიტომ მასში არსებული არაფერი ვერ მოხვდება დასკვნაში.
  • ფაილს შენთვის არასდროს იმეორებს. შედეგი არის დასკვნების სია - პანელის დაწერილი წინადადებები, რომლებშიც მაქსიმუმ სკრიპტის ან ცვლადის სახელია ციტირებული. ყველა სტრიქონი გადის იმავე redactor-ში, რასაც AI ფუნქციები იყენებს, ამიტომ start სკრიპტი, რომელშიც პაროლია ჩაწერილი, პაროლის გარეშე ციტირდება.
  • ხმაურით არასდროს ვარდება. GitHub არ მუშაობს, rate limit, GitHub App-ი წაშლილია, ბრენჩი ჯერ არ არსებობს: თითოეული იქცევა ერთ შენიშვნად, რომ check ვერ გაეშვა. check, რომელიც მთელ ჩანართს ჩამოაგდებდა, უფრო ცუდი იქნებოდა, ვიდრე check-ის გარეშე.
მხოლოდ წაკითხვაშენ ასწორებ, მერე აბამGitHub რეპოზიტორიაბრენჩის headPre-flight checkხე + რამდენიმე ფაილიPre-flight ბარათიყველაზე ცუდი პირველიბმა შენახულიასერვერის startpull, install, boot
სად დგას pre-flight check GitHub deploy-ში

check იმავე ჩატვირთვის ლოგიკას მისდევს, რასაც სერვერი. მას არ აქვს Node ან Go აპლიკაციის ცალკე წარმოდგენა; ის კითხულობს შესვლის ფაილების სიას, რომელზეც startup სკრიპტი ბრუნდება, და ცვლადს, რომელსაც Startup ჩანართი იყენებს თითოეული runtime-ისთვის. როცა ჩატვირთვა იცვლება, check-იც მასთან ერთად იცვლება.

როგორ ვკითხულობთ pre-flight ბარათს#

ბარათი GitHub ჩანართზეა, სათაურით "Pre-flight check", და ერთი ხაზით, რომელშიც წერია რომელი commit და ბრენჩი წაიკითხა. თითოეულ დასკვნას ოთხიდან ერთი დონე აქვს და სია დალაგებულია ისე, რომ ყველაზე ცუდი ზემოთაა:

დონეწარწერა ბარათზერას ნიშნავს
failWill breakაპლიკაცია არ ჩაირთვება, ან ჩაირთვება და მიუწვდომელი იქნება
warnWorth fixingიმუშავებს, მაგრამ ცუდად ან არა ისე, როგორც დაგეგმილი იყო
infoGood to knowკონტექსტი, ან რაღაც, რაც check-მა ვერ გადაწყვიტა
passFineეს ნაწილი ემთხვევა იმას, როგორ ირთვება სერვერი

თითოეულ დასკვნას აქვს სათაური, ერთი წინადადება დეტალებით და - სადაც არის - გასწორება პატარა კოდის ყუთში Copy ღილაკით. გასწორება ამ კონკრეტული სერვერისთვისაა დაწერილი: როცა წერია $SERVER_PORT, ეს ცვლადი ჩატვირთვისას მართლა არის დაყენებული. ღილაკი Re-run check-ს მოთხოვნით ხელახლა უშვებს.

რას ამოწმებს check, სერვერის runtime-ზეა დამოკიდებული. Node.js, Bun, Deno, Go და Python სერვერები სრულ კომპლექტს იღებენ: start ბრძანება, პორტი და host, build, ვერსია. Web hosting-ს აქვს index ფაილის და build-ის შემოწმება. სხვა ტიპის სერვერები, მაგალითად Java, .NET ან Rust, თავიანთ build და start ბრძანებას თვითონ უშვებენ, ამიტომ მათთვის მხოლოდ საიდუმლოების შემოწმებებია და ბარათი ამას პირდაპირ წერს და არ დუმს.

გასაშვები არაფერია: start სკრიპტები და შესვლის ფაილები#

ყველაზე გავრცელებული პრობლემა ისაა, რომ აპლიკაციას სერვერისთვის გასაშვები არაფერი აქვს. კონტეინერი ირთვება, ბრძანებას ვერ პოულობს და ერთ წამში გამოდის. კონსოლში მოკლე ტექსტია და მერე არაფერი, რაც დამაბნეველია, თუ ამას არ ელოდები.

Node.js სერვერზე ჩატვირთვა უშვებს npm install-ს და მერე npm run start-ს. თუ package.json-ში start სკრიპტი არ არის, ის ბრუნდება პირველ შესვლის ფაილზე ფიქსირებული სიიდან: index.js, server.js, app.js, main.js, bot.js, index.mjs, index.cjs, იგივე სახელები src/-ში, და მერე TypeScript ვერსიები, მაგალითად index.ts და src/server.ts (გაშვება ts-node-ით). თუ არც ერთი არ არსებობს, ბარათი აჩვენებს "No start script and no entry file" fail დონეზე.

package.json, რომელიც ამას იწვევს, ჩვეულებრივ ასე გამოიყურება - პროექტი, რომელიც ლეპტოპზე მხოლოდ npm run dev-ით გაუშვიათ:

package.json (before)
{  "name": "my-api",  "main": "src/api.js",  "scripts": {    "dev": "nodemon src/api.js"  },  "dependencies": { "express": "^4.19.2" }}

src/api.js სარეზერვო სახელებში არ შედის და start არ არის. გასწორება ერთი ხაზია:

package.json (after)
{  "scripts": {    "dev": "nodemon src/api.js",    "start": "node src/api.js"  }}

package.json, რომელიც არ იპარსება, ცალკე და ყველაზე წინ ფიქსირდება, რადგან npm მას უარყოფს და შემდეგ აზრი აღარაფერს აქვს. ბარათის შემოთავაზებული გასწორება ისაა, რომ ლოკალურად გაუშვა npm install და წაიკითხო შეცდომა. ჩვეულებრივ მიზეზი ბოლოში დარჩენილი მძიმეა.

დანარჩენ runtime-ებს ამავე შემოწმების საკუთარი ვერსიები აქვთ:

  • Bun უშვებს bun install-ს და მერე bun run start-ს, თუ package.json-ში start სკრიპტია, თორემ Startup ჩანართზე მითითებულ შესვლის ფაილს, თორემ იმავე სარეზერვო სიიდან პირველ ფაილს. თუ Startup ჩანართი ისეთ ფაილს ასახელებს, რომელიც ბრენჩში არ არის, მაგრამ სარეზერვო არსებობს, ბარათი გეუბნება რომელი ფაილი გაეშვება რეალურად და გირჩევს Startup ჩანართზე იგივე დააყენო.
  • Deno უშვებს deno task start-ს deno.json-იდან ან deno.jsonc-იდან. start task-ის გარეშე ის უშვებს Startup ჩანართის შესვლის ფაილს deno run -A-ით - ეს ყველა ნებართვას იძლევა და ბარათი ამას წერს. სარეზერვო სახელებია main.ts, mod.ts, server.ts, index.ts, main.js, src/main.ts და src/index.ts. package.json deno.json-ის გარეშე შენიშვნას იღებს: Deno სერვერზე npm install-ს არავინ უშვებს, ამიტომ ან Deno-ს თვითონ ათქმევინე დამოკიდებულებები, ან გამოიყენე npm: specifier-ები.
  • Python უშვებს Startup ჩანართზე დასახელებულ შესვლის ფაილს. თუ არცერთია დასახელებული, პანელი ეძებს main.py, bot.py, app.py, run.py და __main__.py ამ თანმიმდევრობით და როცა ბმას ინახავ, Startup ჩანართს პირველზე აყენებს. თუ Startup ჩანართზე წერია server.py და ბრენჩში ასეთი ფაილი არ არის, ეს fail-ია და გასწორებაში იმ კანდიდატის სახელია, რომელიც ნაპოვნია.
  • Go აგებს Startup ჩანართზე მითითებულ პაკეტს (GO_MAIN, ნაგულისხმევად .) go build-ით და ჩავარდნილი build start-ს აჩერებს. check-ს სჭირდება go.mod, Go ფაილები ამ საქაღალდეში, package main და func main(). საქაღალდე, რომელშიც ბიბლიოთეკის პაკეტია, ასეთადვე ფიქსირდება, რადგან go build ბიბლიოთეკაზე პროგრამას არ აწარმოებს.

Go-ს შემთხვევა იჭერს განლაგებას, რომელზეც ბევრი ცდება: მოდულის root-ში ბიბლიოთეკის პაკეტია და პროგრამა cmd/server-შია. დააყენე GO_MAIN Startup ჩანართზე ./cmd/server-ზე და დასკვნა მწვანდება. თუ go.mod საერთოდ არ არის, გაუშვი go mod init შენი მოდულის სახელით, მერე go mod tidy და commit-ში ჩადე go.mod-იც და go.sum-იც.

არასწორი პორტი, არასწორი host#

მეორე ყველაზე გავრცელებული პრობლემა აპლიკაციაა, რომელიც კარგად ირთვება და მიუწვდომელია. ეს ყველაზე გამაღიზიანებელია, რადგან კონსოლი წერს "listening", ბრაუზერი კი არაფერს აჩვენებს.

გარედან მხოლოდ სერვერის საკუთარი პორტი მიწვდომადია. პანელი ჩატვირთვისას ორ გარემოს ცვლადს, PORT-ს და SERVER_PORT-ს, ამ პორტზე აყენებს. აპლიკაცია, რომელიც 3000, 5000, 8000 ან 8080-ს მყარად წერს, უსმენს პორტს, რომელზეც არაფერი მარშრუტდება, თუკი შენი გამოყოფილი პორტი შემთხვევით ეს რიცხვი არ არის. ხოლო აპლიკაცია, რომელიც localhost-ზე ან 127.0.0.1-ზეა მიბმული, მხოლოდ საკუთარი კონტეინერიდან მიიღება, რა პორტიც არ უნდა გამოიყენოს. რატომ არის ასე, უფრო სრულად იხილე აქ: game server-ის პორტები განმარტებით - იგივე წესები აპლიკაციებზეც მოქმედებს.

check ჯერ start სკრიპტს კითხულობს, მერე შესვლის ფაილს და ფიქსირებს:

  • start სკრიპტს, რომელიც პორტს ამაგრებს, მაგალითად next start -p 3000 ან --port 8080 (warn);
  • შესვლის ფაილს, რომელიც იძახებს .listen(3000)-ს ან სვამს port = 5000-ს (warn);
  • შესვლის ფაილს, რომელიც localhost-ზე ან 127.0.0.1-ზე ებმის (warn);
  • შესვლის ფაილს, რომელიც კითხულობს process.env.PORT-ს, SERVER_PORT-ს, Bun.env.PORT-ს ან Deno.env.get("PORT")-ს (pass);
  • ვებ სერვერი საერთოდ ვერ მოიძებნა (info) - Discord ან Telegram ბოტისთვის ნორმალურია, ხოლო თუ HTTP გელოდა, ერთხელ კიდევ დააკვირდი.

ეს Express-ის შესვლის ფაილი ორ დასკვნას ერთად იწვევს, მყარად ჩაწერილ პორტს და localhost-ზე მიბმას:

server.js (before)
const express = require('express');const app = express();app.get('/', (req, res) => res.send('ok'));app.listen(3000, 'localhost', () => console.log('listening on 3000'));

ბარათის შემოთავაზებული გასწორება:

server.js (after)
const port = Number(process.env.PORT);app.listen(port, '0.0.0.0', () => console.log(`listening on ${port}`));

იგივე იდეა სხვა runtime-ებში. Python: პორტი წაიკითხე int(os.environ.get("SERVER_PORT", os.environ.get("PORT", 8080)))-ით და გადაეცი host="0.0.0.0". Go: http.ListenAndServe(":"+os.Getenv("PORT"), mux) - ცარიელი ორწერტილი ყველა ინტერფეისზე უსმენს, ხოლო "localhost:8080" სტრიქონი ფიქსირდება. Bun: Bun.serve({ port: Number(process.env.PORT), hostname: '0.0.0.0', fetch }).

Deno-ს ერთი განსაკუთრებული შემთხვევა აქვს. Deno.serve(handler) პორტის გარეშე უსმენს 8000-ს, რომელიც შენი გამოყოფილი პორტი არ არის. ზოგადი check მხოლოდ იტყოდა, რომ ვერ გაარკვია რომელი პორტი გამოიყენება; ეს პრობლემას სახელით ასახელებს:

main.ts
Deno.serve(  { port: Number(Deno.env.get("PORT")), hostname: "0.0.0.0" },  (_req) => new Response("ok"),);

ზოგჯერ ბარათი info დონეზე წერს "Could not tell which port". ეს ხდება მაშინ, როცა სერვერი იქმნება იმ ადგილას, რომელსაც check არ კითხულობს, მაგალითად შესვლის ფაილიდან იმპორტირებულ ფაილში. ეს შეცდომა არ არის; გახსენი ფაილი, რომელიც იძახებს listen-ს და თვალით შეამოწმე.

build-ები, რომლებიც არასდროს გაშვებულა#

build ეტაპის მქონე ფრეიმვორკები განსაკუთრებულად ვარდებიან: start ბრძანება ეძებს build-ის შედეგს, რომელიც არ არსებობს. check ოთხს იცნობს და იცის თითოეული რას აწარმოებს - Next.js აგებს .next-ს, Nuxt აგებს .output-ს, Angular და Vite აგებენ dist-ს. თუ პროექტი ამათგან რომელიმეზეა დამოკიდებული, სამ კითხვას სვამს: უშვებს თუ არა start სკრიპტი, prestart ან postinstall build-ს; თუ არა, არის თუ არა build-ის შედეგი commit-ში; და თუ არც ერთი, ეს fail-ია.

ტიპური Next.js-ის package.json, რომელიც ვარდება:

package.json (before)
{  "scripts": {    "dev": "next dev",    "build": "next build",    "start": "next start"  }}

build არსებობს, მაგრამ სერვერზე მას არავინ იძახებს. ბარათის მოცემული გასწორება ჯერ აგებს და მერე სწორ host-სა და პორტზე ემსახურება:

package.json (after)
{  "scripts": {    "build": "next build",    "start": "next build && next start -H 0.0.0.0 -p $SERVER_PORT"  }}

ალტერნატივებია postinstall, რომელიც build-ს უშვებს, ან build-ის შედეგის commit-ში ჩადება. .next-ის commit მუშაობს და ბარათი მას ატარებს, შეხსენებით, რომ ყოველი push-ის წინ ხელახლა უნდა ააშენო. უმეტესობას ერთ კვირაში ავიწყდება. ჩვენ სერვერზე build-ს ვამჯობინებთ.

start სკრიპტი, რომელიც development სერვერს უშვებს, ცალკე გაფრთხილებაა. next dev, nuxt dev, ng serve და უბრალო vite ნელია, არ არის მინიფიცირებული და ხშირად localhost-ზეა მიბმული. Vite-ისთვის შემოთავაზებული გასწორებაა vite build && vite preview --host 0.0.0.0 --port $SERVER_PORT; Nuxt-ისთვის - nuxt build && node .output/server/index.mjs. პატარა სერვერზე build-ის მეხსიერების მხარეზე წერია Next.js-ის deploy გზამკვლევში.

უბრალო TypeScript ფრეიმვორკის გარეშე იმავე მოპყრობას იღებს. თუ typescript დამოკიდებულებაა და start სკრიპტი უშვებს node dist/index.js-ს, მაგრამ dist/index.js commit-ში არ არის და start-მდე tsc-ს არავინ უშვებს, ბარათი წერს "TypeScript is never compiled" და გირჩევს tsc && node dist/index.js-ს.

runtime-ის ვერსიების შეუსაბამობა#

ერთი მაჟორული ვერსიისთვის დაწერილი პროექტი სხვაზე შეიძლება ვერ დაინსტალირდეს ან ვერ გაეშვას, ჩვეულებრივ native მოდულის ან სინტაქსის ცვლილების გამო. check ადარებს იმას, რასაც რეპოზიტორია ითხოვს, იმასთან, რასაც სერვერი უშვებს.

Node.js-ისთვის ის ჯერ .nvmrc-ს კითხულობს და მერე package.json-ში engines.node-ს. .nvmrc, რომელშიც წერია 20, Node 22-ზე მომუშავე სერვერზე გაფრთხილებაა. engines-ით >=18 დიაპაზონი 18-დან ზევით ყველაფერზე გადის; ^20 ან უბრალო 20 მხოლოდ Node 20-ზე. შემოთავაზებული გასწორებაა ან იმავე ჩანართზე Runtime version-ში შესაბამისი ვერსიის არჩევა, ან ფაილის განახლება. აირჩიე იმის მიხედვით, რა არის სიმართლე: თუ პროექტს მართლა Node 20 სჭირდება, სერვერი შეცვალე; თუ .nvmrc ორი წლის წინანდელი ნარჩენია, ფაილი შეცვალე.

.nvmrc
22

Go-სთვის ის კითხულობს go ხაზს go.mod-ში. თუ go.mod უფრო ახალ Go-ს ითხოვს, ვიდრე სერვერზეა, build ან ყოველ start-წინ ჩამოტვირთავს ახალ toolchain-ს, რასაც ყოველ ჯერზე ქსელი და დისკი სჭირდება, ან build-ზე უარს იტყვის. აირჩიე ეს Go ვერსია ან უფრო ახალი Runtime version-ში, ან დაწია go ხაზი, თუ კოდს ის რეალურად არ სჭირდება.

ვერსიის შემოწმება მხოლოდ მაშინ ეშვება, როცა სერვერის image ასახელებს ვერსიას, რომლის წაკითხვაც check-ს შეუძლია. თუ ვერ გაარკვია, ის გამოცნობის ნაცვლად დუმს.

Python, web hosting და სხვა runtime-ის თავისებურებები#

Python-ს ორი დასკვნა აქვს, რომლებიც სხვა პლატფორმებიდან მოსულებს იჭერს.

სერვერი start-მდე pip-ით აინსტალირებს requirements.txt-ს. პროექტი, რომელიც დამოკიდებულებებს მხოლოდ pyproject.toml-ში აცხადებს, გაფრთხილებას იღებს, რადგან მასში არაფერი ინსტალირდება. გამოიტანე requirements ფაილი და ჩადე commit-ში:

bash
$ pip freeze > requirements.txt$ uv pip compile pyproject.toml -o requirements.txt

ორივე ბრძანება მუშაობს; მეორე ფაილს იმით ზღუდავს, რასაც pyproject.toml აცხადებს, და არა შენს ლოკალურ გარემოში არსებული ყველაფრით. pinning-ზე უფრო დაწვრილებით წერია Python requirements გზამკვლევში.

Procfile ფიქსირდება როგორც წაუკითხავი. სერვერი უშვებს Startup ჩანართზე მითითებულ შესვლის ფაილს და არა Procfile-ში არსებულ ბრძანებას. თუ შენს Procfile-ში წერია web: gunicorn app:app, ეს ბრძანება იგნორდება, ამიტომ დარწმუნდი, რომ შესვლის ფაილი სერვერს თვითონ უშვებს.

Web hosting უფრო მარტივია და უფრო მკაცრი. ჰოსტი საქაღალდეს ისე ემსახურება, როგორიც არის, და npm run build-ს არასდროს უშვებს. check-ს root-ში სჭირდება index.html, index.php ან index.htm. თუ არცერთს პოულობს, მაგრამ ხედავს dist/index.html-ს, build/index.html-ს, out/index.html-ს, public/index.html-ს ან _site/index.html-ს, ამას წერს და გირჩევს აგებული ფაილების commit-ს ან deploy-ის გზის იმ საქაღალდეზე მითითებას. პროექტი build სკრიპტით და commit-ში ჩადებული build-ის გარეშე ამავე მიზეზით ცალკე გაფრთხილებას იღებს. build-ის მხარისთვის იხილე სტატიკური საიტის ჰოსტინგის გზამკვლევი.

საიდუმლოები: commit-ში მოხვედრილი .env და .env.example#

ეს ერთადერთი დასკვნაა, რომელიც უსაფრთხოებას ეხება და არა იმას, ირთვება თუ არა აპლიკაცია, და ყველა ტიპის სერვერზე მუშაობს.

ნებისმიერი ფაილი სახელით .env, .env.local, .env.production, .env.prod, .env.development ან .env.dev, ხის ნებისმიერ ადგილას, fail-ია: "A .env is committed to the repository". მასში არსებული ყველა პაროლი და გასაღები იკითხება ყველას მიერ, ვისაც რეპოზიტორიის წაკითხვა შეუძლია, ყველა commit-ში, მისი დამატების შემდეგ. web hosting-ზე უარესია: ფაილი დანარჩენ საქაღალდესთან ერთად გაიცემა, ამიტომ მისი ჩამოტვირთვა თვითონ საიტიდან შეიძლება.

გასწორება თანმიმდევრობით:

bash
$ git rm --cached .env$ echo ".env" >> .gitignore$ git commit -m "Stop tracking .env"$ git push

მერე შეცვალე მონაცემები - ბაზის პაროლები, API token-ები, ბოტის token-ები - და ახალი .env შექმენი სერვერზე Files ჩანართით. .env GitHub-იდან არასდროს იტვირთება, ამიტომ სერვერზე მხოლოდ ის არის, რაც შენ ჩადე. უფრო ფართო პრაქტიკაზე წერია გარემოს ცვლადები და საიდუმლოები.

.env.example იღებს info დასკვნას, რომელიც ჩამოთვლის მასში გამოცხადებულ გასაღებებს, ოცდაათამდე, რომ ერთი შეხედვით ნახო რა სჭირდება სერვერის .env-ს. მაგალითში მნიშვნელობები არ ჩანს. თუ პროექტი იყენებს dotenv-ს ან python-dotenv-ს და .env.example არ აქვს, ბარათი აღნიშნავს, რომ აპლიკაცია .env-ს კითხულობს და შეგახსენებს, რომ ატვირთო.

რას ვერ იჭერს pre-flight check#

check ფაილებს კითხულობს. არაფერს უშვებს და ეს მის საზღვრებს ადგენს.

  • Runtime შეცდომები. გარემოს ცვლადი, რომელიც აკლია და აპლიკაციას პირველსავე მოთხოვნაზე ანგრევს, ბაზა, რომელიც კავშირზე უარს ამბობს, ბეჭდვითი შეცდომა route-ში - არცერთი ეს ფაილების სიაში არ ჩანს.
  • მეხსიერება. Next.js build, რომელსაც პლანზე მეტი RAM სჭირდება, check-ს გაივლის და build-ის დროს ჩავარდება. როგორ გაარჩიო, წერია Node-ის მეხსიერების ლიმიტებში.
  • არაპირდაპირი პორტები. პორტი, რომელიც კონფიგურაციის ფაილიდან იკითხება ან იმპორტირებულ მოდულშია დაყენებული, შეიძლება გამოჩნდეს როგორც "Could not tell". შეამოწმე ხელით.
  • კერძო დამოკიდებულებები. პაკეტი კერძო registry-დან ინსტალაციისას მონაცემებს საჭიროებს; check ინსტალაციას არ ამოწმებს.
  • ყველაფერი ბრენჩის გარეთ. ატვირთული ფაილები, სერვერის საკუთარი .env და ბაზის შიგთავსი რეპოზიტორიის ნაწილი არ არის.

მწვანე ბარათი ნიშნავს, რომ ჩატვირთვა იპოვის რაღაცას გასაშვებად, სწორ პორტზე, აგებულს და შესაბამის ვერსიაზე. ეს მოსაწყენ პრობლემებს აცილებს, ამიტომ კონსოლში რაც დარჩება, რეალური bug იქნება.

როცა კონსოლი crash-ს აჩვენებს, კონსოლის ჩანართზე "Work on this server with AI" ზოლს აქვს "Server won't start" ვარიანტი, რომელიც აკოპირებს მზა prompt-ს კონსოლის ბოლო ხაზებით. pre-flight დასკვნებიც AI-ის კონტექსტში გადადის, ამიტომ ასისტენტი, რომელსაც რეპოზიტორიის გასწორებას სთხოვ, იმით იწყებს, რაც უკვე ცნობილია, რომ გაფუჭებულია. ბმასა და push-ზე deploy-ს ეხება GitHub deploy-ის გზამკვლევი, ხოლო გადამრთველებზე წერია ჩვენი გზამკვლევების deploy-ების განყოფილებაში.

FAQ#

ბლოკავს თუ არა pre-flight check deploy-ს?

არა. ის გატყობინებს და არ გაჩერებს. შეგიძლია მიაბა რეპოზიტორია fail დონის დასკვნებით და deploy გაგრძელდება და ისე ჩავარდება, როგორც ბარათმა იწინასწარმეტყველა. აზრი ისაა, რომ ეს ადრე ნახო და არა მერე.

რატომ წერს ბარათი, რომ ფაილი აკლია, როცა ის ჩემს რეპოზიტორიაშია?

სამი ჩვეულებრივი მიზეზია: ფაილი სხვა ბრენჩზეა, ვიდრე მიბმული, deploy-ის გზა ისეთ ქვესაქაღალდეზე მიუთითებს, რომელშიც ის არ არის, ან რეპოზიტორია იმდენად დიდია, რომ GitHub-მა ფაილების არასრული სია დააბრუნა, რასაც ბარათი ზემოთ აღნიშნავს. ჯერ ბარათის სათაურ ხაზში ბრენჩის სახელი შეამოწმე.

პრობლემა გავასწორე და push გავაკეთე. რატომ აჩვენებს ბარათი მაინც?

დიდხანს არ უნდა აჩვენოს. ბრენჩის head ყოველ შესვლაზე მოწმდება, ამიტომ ახალი commit ხელახალ წაკითხვას იწვევს. თუ მაინც ჩანს, დააჭირე Re-run და შეამოწმე, რომ push გააკეთე იმ ბრენჩზე, რომელზეც სერვერია მიბმული და არა სხვაზე.

ხედავს თუ არა check ჩემი .env-ის მნიშვნელობებს?

არა. commit-ში მოხვედრილი .env სახელით ფიქსირდება და მისი შიგთავსი არასდროს მოითხოვება. .env.example იკითხება, მაგრამ ბარათზე მხოლოდ გასაღებების სახელები ჩანს. ბარათზე ყველა სტრიქონი ჩვენებამდე redactor-შიც გადის.

რომელ runtime-ებს ფარავს check?

Node.js, Bun, Deno, Go და Python იღებენ start, პორტის, build-ისა და ვერსიის შემოწმებებს; web hosting - index ფაილისა და build-ის შემოწმებებს. სხვა ტიპის სერვერები იღებენ commit-ში მოხვედრილი საიდუმლოების შემოწმებებს და შენიშვნას, რომ runtime შემოწმებები მათზე არ ვრცელდება.

მუშაობს თუ არა GitLab-თან ან Bitbucket-თან?

არა. Git deploy RE:NODE-ზე მხოლოდ GitHub-ისთვისაა, GitHub App-ის მეშვეობით, და check რეპოზიტორიას ამ App-ის წვდომით კითხულობს - ამიტომ კერძო რეპოზიტორიებიც მუშაობს, თუ App-ს ისინი ჩანს.

გამოგადგათ?