Ikviens, kurš izstrādā tīmekļa lietojumprogrammas un mēģina palaist tos savos nepārvaldītajos serveros, zina par garlaicīgo procesu, kas saistīts ar viņu lietojumprogrammu izvietošanu un turpmāko atjauninājumu ieviešanu. Platformas kā pakalpojuma (PaaS) nodrošinātāji ir ļāvuši ērti izvietot tīmekļa lietojumprogrammas, neveicot atsevišķu serveru izveidi un konfigurēšanu, apmaiņā pret nelielu izmaksu pieaugumu un elastības samazināšanos. PaaS, iespējams, ir padarījis lietas vienkāršākas, taču dažreiz mums joprojām ir nepieciešams vai vēlaties izvietot lietojumprogrammas mūsu pašu nepārvaldītajos serveros. Sākotnēji šī tīmekļa lietojumprogrammu izvietošanas procesa automatizēšana var izklausīties milzīga, taču patiesībā vienkārša rīka izveide šī procesa automatizēšanai var būt vienkāršāka, nekā jūs domājat. Tas, cik viegli būs ieviest šo rīku, ir ļoti atkarīgs no tā, cik vienkāršas ir jūsu vajadzības, taču to noteikti nav grūti sasniegt, un tas, iespējams, var palīdzēt ietaupīt daudz laika un pūļu, veicot apnicīgos atkārtojamos tīmekļa lietojumprogrammu fragmentus izvietošanu.
Daudzi izstrādātājiem ir izdomājuši savus veidus, kā automatizēt savu tīmekļa lietojumprogrammu izvietošanas procesus. Tā kā tīmekļa lietojumprogrammu izvietošana ir ļoti atkarīga no precīzas izmantojamās tehnoloģiju kaudzes, šie automatizācijas risinājumi atšķiras. Piemēram, darbības, kas saistītas ar automātiski izvietojot PHP vietni atšķiras no izvietojot Node.js tīmekļa lietojumprogrammu . Pastāv arī citi risinājumi, piemēram, Dokku , kas ir diezgan vispārīgi, un šīs lietas (sauktas par komplektiem) labi darbojas ar plašāku tehnoloģiju kaudzes klāstu.
Šajā apmācībā mēs apskatīsim vienkāršā rīka pamatidejas, ko varat izveidot, lai automatizētu tīmekļa lietojumprogrammu izvietošanu, izmantojot GitHub tīmekļa āķus, veidošanas pakotnes un Procfiles. Prototipa programmas avota kods, kuru mēs izpētīsim šajā rakstā, ir pieejams vietnē GitHub .
Lai automatizētu mūsu tīmekļa lietojumprogrammas izvietošanu, mēs uzrakstīsim vienkāršu Go programmu. Ja jums nav zināms Go, nevilcinieties sekot līdzi, jo šajā rakstā izmantotie kodu uzbūves ir diezgan vienkārši un tiem jābūt viegli saprotamiem. Ja vēlaties, iespējams, diezgan viegli varat visu programmu ievietot izvēlētajā valodā.
Pirms sākat, pārliecinieties, vai jūsu sistēmā ir instalēta izplatīšana Go. Lai instalētu Go, varat sekot oficiālajā dokumentācijā izklāstītās darbības .
nopirkt kredītkartes no hakeriem
Pēc tam jūs varat lejupielādēt šī rīka avota kodu, klonējot GitHub krātuve . Tam vajadzētu atvieglot sekošanu, jo šajā rakstā esošie kodu fragmenti ir apzīmēti ar tiem atbilstošajiem failu nosaukumiem. Ja vēlaties, varat izmēģini tūlīt pat.
Viena no galvenajām Go izmantošanas priekšrocībām šai programmai ir tā, ka mēs varam to izveidot tā, lai mums būtu minimālas ārējās atkarības. Mūsu gadījumā, lai palaistu šo programmu serverī, mums vienkārši jānodrošina, ka mums ir instalēti Git un Bash. Tā kā Go programmas tiek apkopotas statiski saistītos bināros failos, programmu varat apkopot savā datorā, augšupielādēt serverī un palaist gandrīz bez piepūles. Lielākajai daļai citu mūsdienās populāru valodu tas prasītu serverī instalētu mamuta izpildlaika vidi vai tulku, lai tikai palaistu izvietošanas automātiku. Go programmas, kad tas izdarīts pareizi, var būt arī ļoti viegli, izmantojot CPU un RAM - ko jūs vēlaties no šādām programmām.
Izmantojot GitHub Webhooks, ir iespējams konfigurēt savu GitHub repozitoriju tā, lai tas izstarotu notikumus katru reizi, kad kaut kas krātuvē mainās vai kāds lietotājs veic īpašas darbības mitinātajā krātuvē. Tas ļauj lietotājiem abonēt šos notikumus un, izmantojot URL izsaukumus, saņemt paziņojumus par dažādiem notikumiem, kas notiek ap jūsu krātuvi.
Tīmekļa saites izveidošana ir ļoti vienkārša:
GitHub nodrošina plaša dokumentācija par Webhooks un kā tieši viņi strādā, kāda informācija tiek piegādāta lietderīgajā kravā, reaģējot uz dažādiem notikumiem utt. Šī raksta vajadzībām mūs īpaši interesē “Push” pasākums kas tiek izstarots katru reizi, kad kāds virzās uz jebkuru krātuves filiāli.
Mūsdienās kompleksi ir diezgan standarta. Izstrādājumi, ko izmanto daudzi PaaS nodrošinātāji, ļauj pirms lietojumprogrammas izvietošanas norādīt, kā kaudze tiks konfigurēta. Tīmekļa lietojumprogrammu veidošanas uzrakstīšana ir patiešām vienkārša, taču biežāk nekā ātri veicot meklēšanu tīmeklī, jūs varat atrast buildpack, kuru varat izmantot savai tīmekļa lietojumprogrammai bez jebkādām izmaiņām.
Ja esat izvietojis lietojumprogrammu PaaS, piemēram, Heroku, jūs, iespējams, jau zināt, kas ir pakotnes un kur tās atrast. Heroku ir daži visaptveroši dokumentācija par pakotņu struktūru un a dažu labi izveidotu populāru veidņu saraksts .
Mūsu automatizācijas programma izmantos kompilēšanas skriptu, lai sagatavotu lietojumprogrammu pirms tās palaišanas. Piemēram, Heroku veidots Node.js parsē failu package.json, lejupielādē atbilstošu Node.js versiju un lejupielādē lietojumprogrammas NPM atkarības. Ir vērts atzīmēt, ka, lai viss būtu vienkāršs, mūsu prototipa programmā mums nebūs plaša atbalsta veidnēm. Pagaidām mēs pieņemsim, ka buildpack skripti ir rakstīti, lai tos palaistu ar Bash, un ka tie darbosies ar svaigu Ubuntu instalāciju, kāda tā ir. Ja nepieciešams, jūs varat to viegli pagarināt nākotnē, lai apmierinātu ezotērikas vajadzības.
Procfiles ir vienkārši teksta faili, kas ļauj noteikt dažādus procesu veidus, kas ir jūsu lietojumprogrammā. Lielākajā daļā vienkāršo lietojumprogrammu jums ideāli būtu viens 'tīmekļa' process, kas būtu process, kas apstrādā HTTP pieprasījumus.
Rakstīt Procfiles ir viegli. Katrā rindā definējiet vienu procesa veidu, ierakstot tā nosaukumu, kam seko kols, kam seko komanda, kas radīs procesu:
:
Piemēram, ja strādājat ar tīmekļa lietojumprogrammu, kuras pamatā ir Node.js, lai palaistu tīmekļa serveri, izpildiet komandu “mezgls index.js”. Jūs varat vienkārši izveidot Procfile koda bāzes direktorijā un nosaukt to par “Procfile” ar sekojošo:
web: node index.js
Mums prasīs, lai lietojumprogrammas Procfiles definētu procesa veidus, lai pēc koda ievilkšanas tos varētu sākt automātiski.
Mūsu programmā mums jāiekļauj HTTP serveris, kas ļaus mums saņemt ienākošos POST pieprasījumus no GitHub. Mums būs jāvelta kāds URL ceļš, lai apstrādātu šos pieprasījumus no GitHub. Funkcija, kas apstrādās šīs ienākošās kravas, izskatīsies apmēram šādi:
// hook.go type HookOptions struct { App *App Secret string } func NewHookHandler(o *HookOptions) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { evName := r.Header.Get('X-Github-Event') if evName != 'push' { log.Printf('Ignoring '%s' event', evName) return } body, err := ioutil.ReadAll(r.Body) if err != nil { http.Error(w, 'Internal Server Error', http.StatusInternalServerError) return } if o.Secret != '' { ok := false for _, sig := range strings.Fields(r.Header.Get('X-Hub-Signature')) { if !strings.HasPrefix(sig, 'sha1=') { continue } sig = strings.TrimPrefix(sig, 'sha1=') mac := hmac.New(sha1.New, []byte(o.Secret)) mac.Write(body) if sig == hex.EncodeToString(mac.Sum(nil)) { ok = true break } } if !ok { log.Printf('Ignoring '%s' event with incorrect signature', evName) return } } ev := github.PushEvent{} err = json.Unmarshal(body, &ev) if err != nil { log.Printf('Ignoring '%s' event with invalid payload', evName) http.Error(w, 'Bad Request', http.StatusBadRequest) return } if ev.Repo.FullName == nil || *ev.Repo.FullName != o.App.Repo { log.Printf('Ignoring '%s' event with incorrect repository name', evName) http.Error(w, 'Bad Request', http.StatusBadRequest) return } log.Printf('Handling '%s' event for %s', evName, o.App.Repo) err = o.App.Update() if err != nil { return } }) }
Mēs vispirms pārbaudām notikuma veidu, kas ir radījis šo lietderīgo slodzi. Tā kā mūs interesē tikai “push” notikums, visus pārējos notikumus varam ignorēt. Pat ja jūs konfigurējat tīmekļa āķi tā, lai tas izstarotu tikai “push” notikumus, joprojām būs vismaz viens cita veida notikums, kuru jūs varētu sagaidīt savā āķa galapunktā: “ping”. Šī notikuma mērķis ir noteikt, vai tīmekļa āķis vietnē GitHub ir veiksmīgi konfigurēts.
Pēc tam mēs nolasām visu ienākošā pieprasījuma pamattekstu, aprēķinām tā HMAC-SHA1, izmantojot to pašu noslēpumu, kuru izmantosim, lai konfigurētu mūsu tīmekļa āķi, un nosakām ienākošās kravas derīgumu, salīdzinot to ar parakstu, kas iekļauts pieprasījumu. Mūsu programmā mēs ignorējam šo apstiprināšanas darbību, ja noslēpums nav konfigurēts. Sānu piezīmē ir tas, ka var nebūt prātīga ideja lasīt visu ķermeni bez vismaz sava veida augšējās robežas tam, cik daudz datu mēs gribēsim šeit apstrādāt, taču saglabāsim lietas vienkāršas, lai koncentrētos uz kritiskajiem aspektiem šī rīka.
Tad mēs izmantojam struktūru no GitHub klienta bibliotēka Go lai nemaralizētu ienākošo kravu. Tā kā mēs zinām, ka tas ir “push” pasākums, mēs varam izmantot PushEvent strukt . Pēc tam mēs izmantojam standarta Json kodēšanas bibliotēku, lai atdalītu lietderīgo slodzi struktūras instancē. Mēs veicam pāris veselīguma pārbaudes, un, ja viss ir kārtībā, mēs izmantojam funkciju, kas sāk atjaunināt mūsu lietojumprogrammu.
Kad esam saņēmuši paziņojumu par notikumu mūsu tīmekļa saites galapunktā, mēs varam sākt atjaunināt mūsu lietojumprogrammu. Šajā rakstā mēs aplūkosim diezgan vienkāršu šī mehānisma ieviešanu, un noteikti būs vietas uzlabojumiem. Tomēr tam vajadzētu būt kaut kam, kas mūs iesāks ar kādu pamata automatizētu izvietošanas procesu.
Šis process sāksies ar vienkāršu pārbaudi, lai noteiktu, vai mēs pirmo reizi mēģinām izvietot lietojumprogrammu. Mēs to darīsim, pārbaudot, vai pastāv vietējā krātuves direktorija. Ja tā nepastāv, mēs vispirms inicializēsim vietējo repozitoriju:
// app.go func (a *App) initRepo() error { log.Print('Initializing repository') err := os.MkdirAll(a.repoDir, 0755) // Check err cmd := exec.Command('git', '--git-dir='+a.repoDir, 'init') cmd.Stderr = os.Stderr err = cmd.Run() // Check err cmd = exec.Command('git', '--git-dir='+a.repoDir, 'remote', 'add', 'origin', fmt.Sprintf(' [email protected] :%s.git', a.Repo)) cmd.Stderr = os.Stderr err = cmd.Run() // Check err return nil }
Šo metodi App struktūrā var izmantot, lai inicializētu vietējo repozitoriju, un tās mehānismi ir ļoti vienkārši:
cik ir daudz tiešsaistes iepazīšanās vietņu
Kad mums ir inicializēta krātuve, izmaiņu iegūšanai jābūt vienkāršai.
Lai izgūtu izmaiņas no attālās krātuves, mums vienkārši jāizsauc viena komanda:
// app.go func (a *App) fetchChanges() error { log.Print('Fetching changes') cmd := exec.Command('git', '--git-dir='+a.repoDir, 'fetch', '-f', 'origin', 'master:master') cmd.Stderr = os.Stderr return cmd.Run() }
Šādi veicot vietējā repozitorija “git ielādi”, mēs varam izvairīties no problēmām, kad Git nespēj ātri pāriet noteiktos scenārijos. Nevajadzētu paļauties uz piespiedu ielādēm, taču, ja jums ir nepieciešams veikt piespiedu piespiedu tālvadības krātuvi, tas ar to rīkosies ar žēlastību.
Tā kā mēs izmantojam skriptus no buildpacks, lai apkopotu izvietojamās lietojumprogrammas, mūsu uzdevums šeit ir samērā vienkāršs:
// app.go func (a *App) compileApp() error { log.Print('Compiling application') _, err := os.Stat(a.appDir) if !os.IsNotExist(err) { err = os.RemoveAll(a.appDir) // Check err } err = os.MkdirAll(a.appDir, 0755) // Check err cmd := exec.Command('git', '--git-dir='+a.repoDir, '--work-tree='+a.appDir, 'checkout', '-f', 'master') cmd.Dir = a.appDir cmd.Stderr = os.Stderr err = cmd.Run() // Check err buildpackDir, err := filepath.Abs('buildpack') // Check err cmd = exec.Command('bash', filepath.Join(buildpackDir, 'bin', 'detect'), a.appDir) cmd.Dir = buildpackDir cmd.Stderr = os.Stderr err = cmd.Run() // Check err cacheDir, err := filepath.Abs('cache') // Check err err = os.MkdirAll(cacheDir, 0755) // Check err cmd = exec.Command('bash', filepath.Join(buildpackDir, 'bin', 'compile'), a.appDir, cacheDir) cmd.Dir = a.appDir cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr return cmd.Run() }
Mēs vispirms noņemam mūsu iepriekšējo lietojumprogrammu direktoriju (ja tāds ir). Pēc tam mēs izveidojam jaunu un izrakstāmies tajā galvenā filiāles saturu. Pēc tam mēs izmantojam skriptu “detektēt” no konfigurētā buildpack, lai noteiktu, vai lietojumprogramma ir kaut kas, ko mēs varam apstrādāt. Pēc tam, ja nepieciešams, izveidojam direktoriju “kešatmiņa” buildpack kompilēšanas procesam. Tā kā šis direktorijs saglabājas visos būvējumos, var gadīties, ka mums nav jāizveido jauns direktorijs, jo tāds jau pastāv no kāda iepriekšējā kompilēšanas procesa. Šajā brīdī mēs varam izsaukt “compile” skriptu no buildpack un likt tam sagatavot visu nepieciešamo lietojumprogrammai pirms palaišanas. Pareizi izpildot pakotnes, viņi paši var rīkoties ar kešatmiņā saglabāto resursu kešatmiņu un atkārtotu izmantošanu.
Īstenojot šo automatizēto izvietošanas procesu, pirms kompilācijas procesa sākšanas mēs pārtrauksim vecos procesus un pēc tam, kad kompilēšanas fāze būs pabeigta, sāksim jaunos procesus. Lai gan tas atvieglo rīka ieviešanu, tas atstāj dažus potenciāli pārsteidzošus veidus, kā uzlabot automatizēto izvietošanas procesu. Lai uzlabotu šo prototipu, iespējams, varat sākt ar nulles dīkstāves nodrošināšanu atjauninājumu laikā. Pagaidām mēs turpināsim izmantot vienkāršāku pieeju:
// app.go func (a *App) stopProcs() error { log.Print('.. stopping processes') for _, n := range a.nodes { err := n.Stop() if err != nil { return err } } return nil } func (a *App) startProcs() error { log.Print('Starting processes') err := a.readProcfile() if err != nil { return err } for _, n := range a.nodes { err = n.Start() if err != nil { return err } } return nil }
Mūsu prototipā mēs pārtraucam un sākam dažādus procesus, atkārtojot mezglu masīvu, kur katrs mezgls ir process, kas atbilst vienam no lietojumprogrammas gadījumiem (kā konfigurēts pirms šī rīka palaišanas serverī). Savā rīkā mēs sekojam katra mezgla pašreizējam procesa stāvoklim. Mēs tiem uzturam arī atsevišķus žurnālfailus. Pirms visu mezglu palaišanas katram tiek piešķirts unikāls ports, sākot no norādītā porta numura:
// node.go func NewNode(app *App, name string, no int, port int) (*Node, error) { logFile, err := os.OpenFile(filepath.Join(app.logsDir, fmt.Sprintf('%s.%d.txt', name, no)), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) if err != nil { return nil, err } n := &Node{ App: app, Name: name, No: no, Port: port, stateCh: make(chan NextState), logFile: logFile, } go func() { for { next := <-n.stateCh if n.State == next.State { if next.doneCh != nil { close(next.doneCh) } continue } switch next.State { case StateUp: log.Printf('Starting process %s.%d', n.Name, n.No) cmd := exec.Command('bash', '-c', 'for f in .profile.d/*; do source $f; done; '+n.Cmd) cmd.Env = append(cmd.Env, fmt.Sprintf('HOME=%s', n.App.appDir)) cmd.Env = append(cmd.Env, fmt.Sprintf('PORT=%d', n.Port)) cmd.Env = append(cmd.Env, n.App.Env...) cmd.Dir = n.App.appDir cmd.Stdout = n.logFile cmd.Stderr = n.logFile err := cmd.Start() if err != nil { log.Printf('Process %s.%d exited', n.Name, n.No) n.State = StateUp } else { n.Process = cmd.Process n.State = StateUp } if next.doneCh != nil { close(next.doneCh) } go func() { err := cmd.Wait() if err != nil { log.Printf('Process %s.%d exited', n.Name, n.No) n.stateCh <- NextState{ State: StateDown, } } }() case StateDown: log.Printf('Stopping process %s.%d', n.Name, n.No) if n.Process != nil { n.Process.Kill() n.Process = nil } n.State = StateDown if next.doneCh != nil { close(next.doneCh) } } } }() return n, nil } func (n *Node) Start() error { n.stateCh <- NextState{ State: StateUp, } return nil } func (n *Node) Stop() error { doneCh := make(chan int) n.stateCh <- NextState{ State: StateDown, doneCh: doneCh, } <-doneCh return nil }
Īsumā tas var šķist nedaudz sarežģītāks nekā līdz šim paveiktais. Lai lietas būtu viegli uztveramas, sadalīsim iepriekš minēto kodu četrās daļās. Pirmie divi ir funkcijas “NewNode” ietvaros. Kad tiek izsaukts, tas aizpilda struktūras “Mezgls” gadījumu un rada Go rutīnu, kas palīdz sākt un apturēt procesu, kas atbilst šim mezglam. Divas pārējās ir divas metodes “Mezgls” struktūrā: “Sākt” un “Pārtraukt”. Process tiek sākts vai apturēts, nosūtot “ziņojumu” pa noteiktu kanālu, kuru šī moduļa Go rutīna uzrauga. Jūs varat vai nu nosūtīt ziņojumu, lai sāktu procesu, vai citu ziņojumu, lai to apturētu. Tā kā faktiskie soļi, kas saistīti ar procesa sākšanu vai apturēšanu, notiek vienā Go rutīnā, nav izredžu iegūt sacensību apstākļus.
Go rutīna sāk bezgalīgu ciklu, kur tā gaida “ziņojumu” caur “stateCh” kanālu. Ja šim kanālam nodotajā ziņojumā mezgls pieprasa procesa sākšanu (“case StateUp” iekšpusē), tas komandas izpildīšanai izmanto Bash. To darot, tā konfigurē komandu izmantot lietotāja definētos vides mainīgos. Tas arī novirza standarta izejas un kļūdu plūsmas uz iepriekš noteiktu žurnāla failu.
No otras puses, lai apturētu procesu (iekšpusē “case StateDown”), tas to vienkārši nogalina. Šeit jūs, iespējams, varētu būt radošs, un tā vietā, lai procesu nogalinātu, nekavējoties nosūtiet tam SIGTERM un pagaidiet dažas sekundes, pirms to faktiski nogalināt, dodot procesam iespēju graciozi apstāties.
Metodes “Sākt” un “Pārtraukt” atvieglo atbilstošā ziņojuma nodošanu kanālam. Atšķirībā no “Start” metodes, “Stop” metode pirms atgriešanās faktiski gaida, kamēr procesi tiks nogalināti. “Start” vienkārši nosūta kanālam ziņojumu, lai sāktu procesu, un atgriežas.
Visbeidzot, viss, kas mums jādara, ir viss, kas paredzēts programmas galvenajā funkcijā. Šeit mēs ielādēsim un parsēsim konfigurācijas failu, atjaunināsim buildpack, mēģināsim vienreiz atjaunināt mūsu lietojumprogrammu un palaidīsim tīmekļa serveri, lai klausītos ienākošās “push” notikumu kravas no GitHub:
// main.go func main() { cfg, err := toml.LoadFile('config.tml') catch(err) url, ok := cfg.Get('buildpack.url').(string) if !ok { log.Fatal('buildpack.url not defined') } err = UpdateBuildpack(url) catch(err) // Read configuration options into variables repo (string), env ([]string) and procs (map[string]int) // ... app, err := NewApp(repo, env, procs) catch(err) err = app.Update() catch(err) secret, _ := cfg.Get('hook.secret').(string) http.Handle('/hook', NewHookHandler(&HookOptions{ App: app, Secret: secret, })) addr, ok := cfg.Get('core.addr').(string) if !ok { log.Fatal('core.addr not defined') } err = http.ListenAndServe(addr, nil) catch(err) }
Tā kā mēs pieprasām, lai veidošanas paketes būtu vienkāršas Git krātuves, 'UpdateBuildpack' (ieviesta 2007 buildpack.go ) veic tikai “git clone” un “git pull”, ja nepieciešams, ar repozitorija URL, lai atjauninātu buildpack lokālo kopiju.
Gadījumā, ja jūs neesat klonējis krātuve tomēr jūs to varat izdarīt tagad. Ja jums ir instalēta Go izplatīšana, vajadzētu būt iespējai uzreiz sastādīt programmu.
mkdir hopper cd hopper export GOPATH=`pwd` go get github.com/hjr265/toptal-hopper go install github.com/hjr265/toptal-hopper
Šī komandu secība izveidos direktoriju ar nosaukumu hopper, iestatīs to kā GOPATH, ielādēs kodu no GitHub kopā ar nepieciešamajām Go bibliotēkām un apkopos programmu binārā formātā, kuru atradīsit direktorijā “$ GOPATH / bin”. Pirms mēs to varam izmantot serverī, mums jāizveido vienkārša tīmekļa lietojumprogramma, ar kuru to pārbaudīt. Ērtības labad esmu izveidojis vienkāršu “Hello, world” līdzīgu tīmekļa lietojumprogrammu Node.js un augšupielādējis to vietnē vēl viena GitHub repozitorija ko jūs varat dakša un atkārtoti izmantot šim testam. Tālāk mums jāaugšupielādē apkopotais binārs serveris un jāizveido konfigurācijas fails tajā pašā direktorijā:
# config.tml [core] addr = ':26590' [buildpack] url = 'https://github.com/heroku/heroku-buildpack-nodejs.git' [app] repo = 'hjr265/hopper-hello.js' [app.env] GREETING = 'Hello' [app.procs] web = 1 [hook] secret = ''
Pirmā opcija mūsu konfigurācijas failā “core.addr” ir tā, kas ļauj mums konfigurēt mūsu programmas iekšējā tīmekļa servera HTTP portu. Iepriekš minētajā piemērā mēs to esam iestatījuši uz “: 26590”, kas liks programmai noklausīties “push” notikumu kravas vietnē “http: // {host}: 26590 / hook”. Iestatot GitHub tīmekļa āķi, vienkārši aizstājiet “{host}” ar domēna nosaukumu vai IP adresi, kas norāda uz jūsu serveri. Pārliecinieties, vai ports ir atvērts, ja izmantojat sava veida ugunsmūri.
mezgls js tīmekļa lietojumprogrammu ietvars
Pēc tam mēs izvēlamies buildpack, iestatot tā Git URL. Šeit mēs izmantojam Heroku’s Node.js buildpack .
Sadaļā “lietotne” mēs iestatījām “repo” uz pilnu GitHub krātuves nosaukumu, kurā mitināts lietojumprogrammas kods. Tā kā lietojumprogrammas piemēru mitinu vietnē “https://github.com/hjr265/hopper-hello.js”, krātuves pilns nosaukums ir “hjr265 / hopper-hello.js”.
Tad lietojumprogrammai mēs iestatījām dažus vides mainīgos un katra numuru procesu veids mums vajag. Visbeidzot, mēs izvēlamies noslēpumu, lai mēs varētu pārbaudīt ienākošo “push” notikumu lietderīgās slodzes.
Tagad mēs varam palaist mūsu automatizācijas programmu serverī. Ja viss ir pareizi konfigurēts (ieskaitot SSH atslēgu izvietošanu, lai repozitorija būtu pieejama no servera), programmai vajadzētu ielādēt kodu, sagatavot vidi, izmantojot buildpack, un palaist lietojumprogrammu. Tagad viss, kas mums jādara, ir GitHub repozitorijā iestatīt tīmekļa āķi, lai izstarotu push notikumus un norādītu uz “http: // {host}: 26590 / hook”. Noteikti aizstājiet “{host}” ar domēna nosaukumu vai IP adresi, kas norāda uz jūsu serveri.
Lai beidzot pārbaude to, veiciet dažas izmaiņas lietojumprogrammas piemērā un virziet tos uz GitHub. Jūs pamanīsit, ka automatizācijas rīks nekavējoties sāks darboties un atjauninās krātuvi serverī, apkopos lietojumprogrammu un restartēs to.
No lielākās pieredzes mēs varam pateikt, ka tas ir kaut kas diezgan noderīgs. Prototipa lietojumprogramma, kuru esam sagatavojuši šajā rakstā, var nebūt tā, ko jūs vēlētos izmantot ražošanas sistēmā, kāda tā ir. Ir daudz iespēju uzlabot. Šādam rīkam vajadzētu būt labākai kļūdu apstrādei, atbalstīt graciozus izslēgšanu / restartēšanu, un jūs varat izmantot procesu Docker, lai saturētu procesus, nevis tieši tos palaistu. Var būt prātīgāk izdomāt, kas tieši jums nepieciešams jūsu konkrētajā gadījumā, un izdomāt tam automatizācijas programmu. Vai varbūt izmantojiet kādu citu, daudz stabilāku, laika gaitā pārbaudītu risinājumu, kas pieejams visā internetā. Bet, ja vēlaties ieviest kaut ko ļoti pielāgotu, es ceru, ka šis raksts jums palīdzēs to izdarīt un parādīs, cik daudz laika un pūļu jūs varētu ietaupīt ilgtermiņā, automatizējot tīmekļa lietojumprogrammu izvietošanas procesu.
Saistīts: Pastiprināta Git plūsma