Werf 1.1 release: mga pagpapabuti sa tagabuo ngayon at mga plano para sa hinaharap

Werf 1.1 release: mga pagpapabuti sa tagabuo ngayon at mga plano para sa hinaharap

werf ay ang aming open source na GitOps CLI utility para sa pagbuo at paghahatid ng mga application sa Kubernetes. Gaya ng ipinangako, paglabas ng bersyon v1.0 minarkahan ang simula ng pagdaragdag ng mga bagong feature sa werf at pagrerebisa ng mga tradisyonal na diskarte. Ngayon kami ay nalulugod na ipakita ang release v1.1, na isang malaking hakbang sa pag-unlad at isang pundasyon para sa hinaharap kolektor werf. Ang bersyon ay kasalukuyang magagamit sa channel 1.1 ea.

Ang batayan ng pagpapalabas ay ang bagong arkitektura ng imbakan ng entablado at pag-optimize ng gawain ng parehong mga kolektor (para sa Stapel at Dockerfile). Binubuksan ng bagong arkitektura ng storage ang posibilidad ng pagpapatupad ng mga distributed assemblies mula sa maraming host at parallel assemblies sa parehong host.

Kasama sa pag-optimize ng trabaho ang pag-alis ng mga hindi kinakailangang kalkulasyon sa yugto ng pagkalkula ng mga lagda sa yugto at pagpapalit ng mga mekanismo para sa pagkalkula ng mga checksum ng file sa mga mas mahusay. Binabawasan ng optimization na ito ang average na oras ng pagbuo ng proyekto gamit ang werf. At idle build, kapag ang lahat ng mga yugto ay umiiral sa cache yugto-imbakan, ngayon ay talagang mabilis. Sa karamihan ng mga kaso, ang pag-restart ng build ay tatagal ng mas mababa sa 1 segundo! Nalalapat din ito sa mga pamamaraan para sa pag-verify ng mga yugto sa proseso ng gawain ng mga koponan. werf deploy ΠΈ werf run.

Gayundin sa release na ito, lumitaw ang isang diskarte para sa pag-tag ng mga larawan ayon sa nilalaman - pag-tag na nakabatay sa nilalaman, na ngayon ay pinagana bilang default at ang tanging inirerekomenda.

Tingnan natin ang mga pangunahing inobasyon sa werf v1.1, at sabay na sasabihin sa iyo ang tungkol sa mga plano para sa hinaharap.

Ano ang nagbago sa werf v1.1?

Bagong format ng pagpapangalan ng yugto at algorithm para sa pagpili ng mga yugto mula sa cache

Panuntunan sa pagbuo ng bagong pangalan ng entablado. Ngayon, ang bawat yugto ng pagbuo ay bumubuo ng isang natatanging pangalan ng yugto, na binubuo ng 2 bahagi: isang lagda (tulad ng nangyari sa v1.0) at isang natatanging pansamantalang identifier.

Halimbawa, maaaring ganito ang hitsura ng buong pangalan ng larawan ng entablado:

werf-stages-storage/myproject:d2c5ad3d2c9fcd9e57b50edd9cb26c32d156165eb355318cebc3412b-1582656767835

...o sa pangkalahatan:

werf-stages-storage/PROJECT:SIGNATURE-TIMESTAMP_MILLISEC

Narito:

  • SIGNATURE ay isang stage signature, na kumakatawan sa identifier ng stage content at depende sa history ng mga pag-edit sa Git na humantong sa content na ito;
  • TIMESTAMP_MILLISEC ay isang garantisadong natatanging pagkakakilanlan ng larawan na nabuo sa oras na gumawa ng bagong larawan.

Ang algorithm para sa pagpili ng mga yugto mula sa cache ay batay sa pagsuri sa kaugnayan ng Git commits:

  1. Kinakalkula ng Werf ang lagda ng isang tiyak na yugto.
  2. Π’ yugto-imbakan Maaaring may ilang yugto para sa isang naibigay na lagda. Pinipili ni Werf ang lahat ng mga yugto na tumutugma sa lagda.
  3. Kung ang kasalukuyang yugto ay naka-link sa Git (git-archive, custom na yugto na may mga Git patch: install, beforeSetup, setup; o git-latest-patch), pagkatapos ay pipiliin lamang ng werf ang mga yugtong iyon na nauugnay sa isang commit na isang ninuno ng kasalukuyang commit (kung saan tinatawag ang build).
  4. Mula sa natitirang angkop na mga yugto, pipiliin ang isa - ang pinakaluma ayon sa petsa ng paglikha.

Ang isang yugto para sa iba't ibang mga sangay ng Git ay maaaring magkaroon ng parehong lagda. Ngunit pipigilan ng werf ang cache na nauugnay sa iba't ibang sangay na gamitin sa pagitan ng mga sangay na ito, kahit na tumutugma ang mga lagda.

β†’ Dokumentasyon.

Bagong algorithm para sa paglikha at pag-save ng mga yugto sa imbakan ng entablado

Kung, kapag pumipili ng mga yugto mula sa cache, ang werf ay hindi nakakahanap ng angkop na yugto, kung gayon ang proseso ng pag-assemble ng isang bagong yugto ay sinimulan.

Tandaan na ang maraming proseso (sa isa o higit pang mga host) ay maaaring magsimulang bumuo ng parehong yugto nang humigit-kumulang sa parehong oras. Gumagamit ang Werf ng optimistikong blocking algorithm yugto-imbakan sa sandali ng pag-save ng bagong nakolektang imahe sa yugto-imbakan. Sa ganitong paraan, kapag handa na ang bagong stage build, haharang si werf yugto-imbakan at nagse-save ng bagong nakolektang larawan doon lamang kung wala nang angkop na larawan doon (sa pamamagitan ng lagda at iba pang mga parameter - tingnan ang bagong algorithm para sa pagpili ng mga yugto mula sa cache).

Ang isang bagong assemble na imahe ay ginagarantiyahan na magkaroon ng isang natatanging identifier sa pamamagitan ng TIMESTAMP_MILLISEC (tingnan ang bagong format ng pagpapangalan sa yugto). Kung sakaling nasa yugto-imbakan may makikitang angkop na larawan, itatapon ni werf ang bagong pinagsama-samang larawan at gagamitin ang larawan mula sa cache.

Sa madaling salita: ang unang proseso upang matapos ang pagbuo ng imahe (ang pinakamabilis) ay magkakaroon ng karapatang iimbak ito sa mga yugto-imbakan (at pagkatapos ay ang nag-iisang imaheng ito na gagamitin para sa lahat ng mga build). Ang isang mabagal na proseso ng pagbuo ay hindi kailanman hahadlang sa isang mas mabilis na proseso mula sa pag-save ng mga resulta ng pagbuo ng kasalukuyang yugto at paglipat sa susunod na build.

β†’ Dokumentasyon.

Pinahusay na pagganap ng tagabuo ng Dockerfile

Sa ngayon, ang pipeline ng mga yugto para sa isang imahe na binuo mula sa isang Dockerfile ay binubuo ng isang yugto - dockerfile. Kapag kinakalkula ang lagda, ang checksum ng mga file ay kinakalkula context, na gagamitin sa panahon ng pagpupulong. Bago ang pagpapahusay na ito, ang werf ay recursively naglakad sa lahat ng mga file at nakakuha ng checksum sa pamamagitan ng pagbubuod ng konteksto at mode ng bawat file. Simula sa v1.1, ang werf ay maaaring gumamit ng mga kalkuladong checksum na nakaimbak sa isang Git repository.

Ang algorithm ay batay sa git ls-puno. Isinasaalang-alang ng algorithm ang mga talaan sa .dockerignore at binabagtas ang file tree nang paulit-ulit lamang kung kinakailangan. Kaya, kami ay decoupled mula sa pagbabasa ng file system, at ang pagtitiwala ng algorithm sa laki context ay hindi makabuluhan.

Sinusuri din ng algorithm ang mga hindi sinusubaybayang file at, kung kinakailangan, isinasaalang-alang ang mga ito sa checksum.

Pinahusay na pagganap kapag nag-i-import ng mga file

Ang mga bersyon ng werf v1.1 ay gumagamit ng isang rsync server kapag pag-import ng mga file mula sa mga artifact at larawan. Dati, ang pag-import ay ginawa sa dalawang hakbang gamit ang isang directory mount mula sa host system.

Ang pagganap ng pag-import sa macOS ay hindi na limitado ng mga volume ng Docker, at kumpleto ang mga pag-import sa parehong tagal ng oras gaya ng Linux at Windows.

Pag-tag na nakabatay sa nilalaman

Sinusuportahan ng Werf v1.1 ang tinatawag na pag-tag ayon sa nilalaman ng imahe - pag-tag na nakabatay sa nilalaman. Ang mga tag ng mga nagresultang larawan ng Docker ay nakasalalay sa mga nilalaman ng mga larawang ito.

Kapag pinapatakbo ang utos werf publish --tags-by-stages-signature o werf ci-env --tagging-strategy=stages-signature nai-publish na mga larawan ng tinatawag na lagda sa entablado larawan. Ang bawat larawan ay na-tag ng sarili nitong lagda ng mga yugto ng larawang ito, na kinakalkula ayon sa parehong mga panuntunan tulad ng regular na lagda ng bawat yugto nang hiwalay, ngunit isang pangkalahatang identifier ng larawan.

Ang lagda ng mga yugto ng imahe ay nakasalalay sa:

  1. ang mga nilalaman ng larawang ito;
  2. kasaysayan ng mga pagbabago sa Git na humantong sa nilalamang ito.

Ang isang Git repository ay palaging may mga dummy commit na hindi nagbabago sa mga nilalaman ng mga file ng imahe. Halimbawa, nag-commit na may mga komento lang o nag-merge commit, o nag-commit na nagbabago sa mga file na iyon sa Git na hindi mai-import sa larawan.

Kapag gumagamit ng content-based na pag-tag, malulutas ang mga problema sa hindi kinakailangang pag-restart ng mga application pod sa Kubernetes dahil sa mga pagbabago sa pangalan ng larawan, kahit na hindi nagbago ang mga nilalaman ng larawan. Sa pamamagitan ng paraan, ito ay isa sa mga dahilan na pumipigil sa pag-iimbak ng maraming mga microservice ng isang application sa isang solong Git repository.

Gayundin, ang pag-tag na nakabatay sa nilalaman ay isang mas maaasahang paraan ng pag-tag kaysa sa pag-tag sa mga sangay ng Git, dahil ang nilalaman ng mga nagreresultang larawan ay hindi nakadepende sa pagkakasunud-sunod kung saan ang mga pipeline ay isinasagawa sa CI system para sa pag-assemble ng maraming commit ng parehong sangay.

Mahalagang: simula ngayon yugto-pirma - Ay ang tanging inirerekomendang diskarte sa pag-tag. Gagamitin ito bilang default sa command werf ci-env (maliban kung tahasan mong tinukoy ang ibang scheme ng pag-tag).

β†’ Dokumentasyon. Ang isang hiwalay na publikasyon ay ilalaan din sa tampok na ito. NA-UPDATE (Abril 3): Artikulo na may mga detalye nai-publish.

Mga antas ng pag-log

Ang gumagamit ay mayroon na ngayong pagkakataon na kontrolin ang output, itakda ang antas ng pag-log at magtrabaho kasama ang impormasyon sa pag-debug. Idinagdag ang mga opsyon --log-quiet, --log-verbose, --log-debug.

Bilang default, ang output ay naglalaman ng pinakamababang impormasyon:

Werf 1.1 release: mga pagpapabuti sa tagabuo ngayon at mga plano para sa hinaharap

Kapag gumagamit ng verbose output (--log-verbose) makikita mo kung paano gumagana ang werf:

Werf 1.1 release: mga pagpapabuti sa tagabuo ngayon at mga plano para sa hinaharap

Detalyadong output (--log-debug), bilang karagdagan sa impormasyon sa pag-debug ng werf, naglalaman din ng mga log ng mga ginamit na aklatan. Halimbawa, makikita mo kung paano nangyayari ang pakikipag-ugnayan sa Docker Registry, at itatala din ang mga lugar kung saan ginugugol ang malaking tagal ng oras:

Werf 1.1 release: mga pagpapabuti sa tagabuo ngayon at mga plano para sa hinaharap

Mga karagdagang plano

Warning! Ang mga opsyon na inilarawan sa ibaba ay minarkahan v1.1 ay magiging available sa bersyong ito, marami sa kanila sa malapit na hinaharap. Darating ang mga update sa pamamagitan ng mga auto-update kapag gumagamit ng multiwerf. Ang mga feature na ito ay hindi nakakaapekto sa stable na bahagi ng v1.1 na mga function; ang kanilang hitsura ay hindi mangangailangan ng manu-manong interbensyon ng user sa mga kasalukuyang configuration.

Buong suporta para sa iba't ibang mga pagpapatupad ng Docker Registry (BAGO)

Ang layunin ay para sa user na gumamit ng custom na pagpapatupad nang walang mga paghihigpit kapag gumagamit ng werf.

Sa kasalukuyan, natukoy namin ang sumusunod na hanay ng mga solusyon kung saan ginagarantiyahan namin ang buong suporta:

  • Default (library/registry)*,
  • AWS ECR
  • Azure*,
  • Docker Hub
  • GCR*,
  • Mga Package ng GitHub
  • GitLab Registry*,
  • Magkimkim*,
  • Quay.

Ang mga solusyon na kasalukuyang ganap na sinusuportahan ng werf ay minarkahan ng asterisk. Para sa iba mayroong suporta, ngunit may mga limitasyon.

Dalawang pangunahing problema ang maaaring makilala:

  • Hindi sinusuportahan ng ilang solusyon ang pag-alis ng tag gamit ang Docker Registry API, na pumipigil sa mga user na gamitin ang awtomatikong paglilinis ng werf. Ito ay totoo para sa AWS ECR, Docker Hub, at GitHub Packages.
  • Ang ilang mga solusyon ay hindi sumusuporta sa tinatawag na mga nested repository (Docker Hub, GitHub Packages at Quay) o kaya, ngunit ang user ay dapat gumawa ng mga ito nang manu-mano gamit ang UI o API (AWS ECR).

Ating lutasin ang mga ito at ang iba pang mga problema gamit ang mga katutubong API ng mga solusyon. Kasama rin sa gawaing ito ang pagsakop sa buong cycle ng pagpapatakbo ng werf na may mga pagsubok para sa bawat isa sa kanila.

Ibinahagi ang pagbuo ng imahe (↑)

  • Bersyon: v1.2 v1.1 (ang priyoridad para sa pagpapatupad ng tampok na ito ay nadagdagan)
  • Mga Petsa: Marso-Abril Marso
  • Problema

Sa ngayon, ang werf v1.0 at v1.1 ay magagamit lamang sa isang nakalaang host para sa mga pagpapatakbo ng pagbuo at pag-publish ng mga larawan at pag-deploy ng application sa Kubernetes.

Upang buksan ang mga posibilidad ng distributed work of werf, kapag ang build at deployment ng mga application sa Kubernetes ay inilunsad sa ilang arbitrary hosts at hindi nai-save ng mga host na ito ang kanilang estado sa pagitan ng mga build (temporary runners), kailangan ng werf na ipatupad ang kakayahang gamitin ang Docker Registry bilang isang tindahan sa entablado.

Dati, noong dapp pa ang tawag sa werf project, may ganitong pagkakataon. Gayunpaman, nakatagpo kami ng ilang isyu na kailangang isaalang-alang kapag ipinapatupad ang functionality na ito sa werf.

Nota. Ang tampok na ito ay hindi nangangailangan ng kolektor na magtrabaho sa loob ng mga pod ng Kubernetes, dahil Upang gawin ito, kailangan mong alisin ang pag-asa sa lokal na Docker server (sa Kubernetes pod ay walang access sa lokal na Docker server, dahil ang proseso mismo ay tumatakbo sa isang lalagyan, at ang werf ay hindi at hindi sumusuporta nagtatrabaho sa server ng Docker sa network). Ang suporta para sa pagpapatakbo ng Kubernetes ay ipapatupad nang hiwalay.

Opisyal na suporta para sa GitHub Actions (BAGO)

Kasama ang dokumentasyon ng werf (mga seksyon sanggunian ΠΈ gabayan), pati na rin ang opisyal na GitHub Action para sa pagtatrabaho sa werf.

Bilang karagdagan, papayagan nito ang werf na magtrabaho sa mga ephemeral runner.

Ang mga mekanika ng pakikipag-ugnayan ng user sa CI system ay ibabatay sa paglalagay ng mga label sa mga pull request upang simulan ang ilang partikular na pagkilos para buuin/ilunsad ang application.

Lokal na pag-unlad at pag-deploy ng mga application na may werf (↓)

  • Bersyon: v1.1
  • Mga Petsa: Enero-Pebrero Abril
  • Problema

Ang pangunahing layunin ay upang makamit ang isang pinag-isang config para sa pag-deploy ng mga application sa parehong lokal at sa produksyon, nang walang kumplikadong mga aksyon, sa labas ng kahon.

Kinakailangan din ng werf na magkaroon ng operating mode kung saan magiging maginhawang i-edit ang application code at agad na makatanggap ng feedback mula sa tumatakbong application para sa pag-debug.

Bagong algorithm sa paglilinis (BAGO)

Sa kasalukuyang bersyon ng werf v1.1 sa pamamaraan cleanup Walang probisyon para sa paglilinis ng mga larawan para sa scheme ng pag-tag na nakabatay sa nilalaman - maiipon ang mga larawang ito.

Gayundin, ang kasalukuyang bersyon ng werf (v1.0 at v1.1) ay gumagamit ng iba't ibang mga patakaran sa paglilinis para sa mga larawang na-publish sa ilalim ng mga scheme ng pag-tag: Git branch, Git tag o Git commit.

Isang bagong algorithm para sa paglilinis ng mga larawan batay sa kasaysayan ng mga commit sa Git, na pinag-isa para sa lahat ng mga scheme ng pag-tag, ay naimbento:

  • Panatilihin ang hindi hihigit sa N1 na mga larawang nauugnay sa N2 pinakabagong mga commit para sa bawat git HEAD (mga sangay at tag).
  • Mag-imbak ng hindi hihigit sa N1 stage na mga larawang nauugnay sa N2 pinakahuling mga commit para sa bawat git HEAD (mga sanga at tag).
  • I-imbak ang lahat ng larawang ginagamit sa anumang mga mapagkukunan ng Kubernetes cluster (lahat ng kube context ng configuration file at namespaces ay na-scan; maaari mong limitahan ang gawi na ito gamit ang mga espesyal na opsyon).
  • I-store ang lahat ng larawang ginagamit sa mga manifest ng configuration ng mapagkukunan na naka-save sa mga release ng Helm.
  • Maaaring tanggalin ang isang imahe kung hindi ito nauugnay sa anumang HEAD mula sa git (halimbawa, dahil ang kaukulang HEAD mismo ay tinanggal) at hindi ginagamit sa anumang mga manifest sa cluster ng Kubernetes at sa mga release ng Helm.

Parallel image building (↓)

  • Bersyon: v1.1
  • Mga Petsa: Enero-Pebrero Abril*

Kinokolekta ng kasalukuyang bersyon ng werf ang mga larawan at artifact na inilarawan sa werf.yaml, sunud-sunod. Kinakailangang i-parallelize ang proseso ng pag-assemble ng mga independiyenteng yugto ng mga imahe at artifact, pati na rin magbigay ng maginhawa at nagbibigay-kaalaman na output.

* Tandaan: ang deadline ay inilipat dahil sa tumaas na priyoridad para sa pagpapatupad ng distributed assembly, na magdaragdag ng higit pang horizontal scaling na mga kakayahan, pati na rin ang paggamit ng werf sa GitHub Actions. Ang parallel assembly ay ang susunod na hakbang sa pag-optimize, na nagbibigay ng vertical scalability kapag nag-assemble ng isang proyekto.

Paglipat sa Helm 3 (↓)

  • Bersyon: v1.2
  • Mga Petsa: Pebrero-Marso Mayo*

Kasama ang paglipat sa bagong codebase Helm 3 at isang napatunayan, maginhawang paraan upang i-migrate ang mga kasalukuyang installation.

* Tandaan: ang paglipat sa Helm 3 ay hindi magdaragdag ng mga makabuluhang feature sa werf, dahil ang lahat ng pangunahing feature ng Helm 3 (3-way-merge at walang tiller) ay ipinatupad na sa werf. Bukod dito, mayroon si werf karagdagang mga tampok bilang karagdagan sa mga ipinahiwatig. Gayunpaman, ang paglipat na ito ay nananatili sa aming mga plano at ipapatupad.

Jsonnet para sa paglalarawan ng configuration ng Kubernetes (↓)

  • Bersyon: v1.2
  • Mga Petsa: Enero-Pebrero Abril-Mayo

Susuportahan ng Werf ang mga paglalarawan ng configuration para sa Kubernetes sa Jsonnet na format. Kasabay nito, mananatiling tugma ang werf sa Helm at magkakaroon ng pagpipilian ng format ng paglalarawan.

Ang dahilan ay ang mga template ng Go, ayon sa maraming tao, ay may mataas na hadlang sa pagpasok, at ang pagiging madaling maunawaan ng code ng mga template na ito ay naghihirap din.

Isinasaalang-alang din ang posibilidad ng pagpapakilala ng iba pang mga sistema ng paglalarawan ng configuration ng Kubernetes (halimbawa, Kustomize).

Nagtatrabaho sa loob ng Kubernetes (↓)

  • Bersyon: v1.2
  • Petsa: Abril-Mayo Mayo-Hunyo

Layunin: Tiyaking nabuo ang mga larawan at naihatid ang application gamit ang mga runner sa Kubernetes. Yung. Maaaring bumuo, mag-publish, maglinis, at mag-deploy ng mga bagong larawan nang direkta mula sa mga pod ng Kubernetes.

Upang ipatupad ang kakayahang ito, kailangan mo munang makabuo ng mga distributed na larawan (tingnan ang punto sa itaas).

Nangangailangan din ito ng suporta para sa operating mode ng builder na walang Docker server (i.e. Kaniko-like build o build sa userspace).

Susuportahan ng Werf ang pagbuo sa Kubernetes hindi lamang sa Dockerfile, kundi pati na rin sa Stapel builder nito na may mga incremental na muling pagtatayo at Ansible.

Isang hakbang tungo sa bukas na pag-unlad

Mahal namin ang aming komunidad (GitHub, Telegrama) at gusto naming mas marami pang tao ang tumulong na pahusayin ang werf, maunawaan ang direksyong tinatahak namin, at makilahok sa pag-unlad.

Kamakailan lang ay napagpasyahan na lumipat sa Mga board ng proyekto ng GitHub upang maihayag ang proseso ng pagtatrabaho ng aming koponan. Ngayon ay makikita mo na ang mga agarang plano, pati na rin ang kasalukuyang gawain sa mga sumusunod na lugar:

Maraming gawain ang nagawa sa mga isyu:

  • Inalis ang mga hindi nauugnay.
  • Ang mga umiiral na ay dinadala sa isang solong format, na may sapat na bilang ng mga detalye at detalye.
  • Ang mga bagong isyu sa mga ideya at mungkahi ay naidagdag.

Paano paganahin ang bersyon v1.1

Ang bersyon ay kasalukuyang magagamit sa channel 1.1 ea (sa mga channel matatag ΠΈ bato-solid lalabas ang mga release habang nangyayari ang stabilization, gayunpaman ea ang kanyang sarili ay sapat na matatag para sa paggamit, dahil dumaan sa mga channel alpha ΠΈ beta). Na-activate sa pamamagitan ng multiwerf sa sumusunod na paraan:

source $(multiwerf use 1.1 ea)
werf COMMAND ...

Konklusyon

Ang bagong stage storage architecture at builder optimizations para sa Stapel at Dockerfile builders ay nagbubukas ng posibilidad na ipatupad ang mga distributed at parallel build sa werf. Malapit nang lumabas ang mga feature na ito sa parehong v1.1 na release at awtomatikong magiging available sa pamamagitan ng mekanismo ng auto-update (para sa mga user multiwerf).

Sa release na ito, isang diskarte sa pag-tag batay sa nilalaman ng imahe ay idinagdag - pag-tag na nakabatay sa nilalaman, na naging default na diskarte. Ang pangunahing command log ay na-rework din: werf build, werf publish, werf deploy, werf dismiss, werf cleanup.

Ang susunod na makabuluhang hakbang ay ang magdagdag ng mga distributed assemblies. Ang mga distributed build ay naging mas mataas na priyoridad kaysa sa parallel build mula noong v1.0 dahil nagdaragdag sila ng higit na halaga sa werf: vertical scaling ng mga builder at suporta para sa ephemeral builder sa iba't ibang CI/CD system, pati na rin ang kakayahang gumawa ng opisyal na suporta para sa GitHub Actions . Samakatuwid, ang mga deadline ng pagpapatupad para sa parallel assemblies ay inilipat. Gayunpaman, nagsusumikap kaming ipatupad ang parehong mga posibilidad sa lalong madaling panahon.

Sundan ang balita! At huwag kalimutang bisitahin kami sa GitHubpara gumawa ng isyu, maghanap ng umiiral na isyu at magdagdag ng plus, gumawa ng PR, o panoorin lang ang pagbuo ng proyekto.

PS

Basahin din sa aming blog:

Pinagmulan: www.habr.com

Magdagdag ng komento